]> www.fi.muni.cz Git - slotcarman.git/commitdiff
Proof-of-concept implementation.
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Tue, 30 Nov 2010 22:33:50 +0000 (23:33 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Tue, 30 Nov 2010 22:33:50 +0000 (23:33 +0100)
SCX/CRC.pm [new file with mode: 0755]
SCX/Reader.pm [new file with mode: 0644]
digest [new file with mode: 0755]
ttymon [new file with mode: 0755]

diff --git a/SCX/CRC.pm b/SCX/CRC.pm
new file mode 100755 (executable)
index 0000000..300cb53
--- /dev/null
@@ -0,0 +1,58 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+package SCX::CRC;
+
+our @crctable;
+
+sub import {
+       return if @crctable;
+
+       my @table = (0x31);
+
+       for my $i (1..7) {
+               my $n = 2 * $table[-1];
+               push @table, $n > 0xff ? ($n ^ 0x31) & 0xff: $n;
+       }
+
+       @crctable = (0x00);
+
+#      print "Table = ", join(' ', map { sprintf("%02x", $_) } @table), "\n";
+
+       for my $i (0x01 .. 0xff) {
+               $crctable[$i] ^= $table[0] if $i & 0x01;
+               $crctable[$i] ^= $table[1] if $i & 0x02;
+               $crctable[$i] ^= $table[2] if $i & 0x04;
+               $crctable[$i] ^= $table[3] if $i & 0x08;
+               $crctable[$i] ^= $table[4] if $i & 0x10;
+               $crctable[$i] ^= $table[5] if $i & 0x20;
+               $crctable[$i] ^= $table[6] if $i & 0x40;
+               $crctable[$i] ^= $table[7] if $i & 0x80;
+       }
+
+#      print "CRCtable = ", join(' ', map { sprintf("%02x", $_) } @crctable), "\n";
+}
+
+sub digest_str {
+       my ($str) = @_;
+
+       return digest(unpack("C*", $str));
+
+}
+
+sub digest {
+       my (@bytes) = @_;
+
+       my $res = 0;
+
+       for my $byte (@bytes) {
+               my $idx = $byte ^ $res;
+               $res = $crctable[$idx];
+       }
+
+       return $res ^ 0xbb;
+}
+
+1;
+
diff --git a/SCX/Reader.pm b/SCX/Reader.pm
new file mode 100644 (file)
index 0000000..1b7c44f
--- /dev/null
@@ -0,0 +1,114 @@
+#!/usr/bin/perl -w
+
+package SCX::Reader;
+
+use Time::HiRes qw(gettimeofday tv_interval);
+use FileHandle;
+use SCX::CRC;
+
+our $PACKET_SIZE = 10;
+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";
+       
+       system 'stty', '-F', $portname, '115200', 'raw';
+       if ($?) {
+               die "stty died with code $? (no permissions?)";
+       }
+
+       open my $tty, '<:raw', $portname
+               or die "Can't open $portname: $!";
+
+       my $logfile = $args->{logfile};
+       my $log_gen = 0;
+
+       open my $logfh, '>', "$logfile.$log_gen"
+       or die "Can't open $logfile.$log_gen: $!";
+
+       my $now = gettimeofday;
+
+       my $self = {
+               portname  => $portname,
+               fh        => $tty,
+               logfile   => $logfile,
+               logfh     => $logfh,
+               log_gen   => $log_gen,
+               log_start => $now,
+               starttime => $now,
+               callback  => $callback,
+               bytes     => [],
+       };
+
+       bless $self, $class;
+
+       return $self;
+}
+
+sub fh { return shift->{fh}; }
+
+sub read {
+       my ($self) = @_;
+
+       my $data;
+       my $bytes_read = sysread $self->fh, $data, $PACKET_SIZE;
+       die "Read error on $self->{portname}: $!"
+               if !$bytes_read;
+
+       my $now = gettimeofday;
+       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}: $!";
+               $self->{logfh} = $fh;
+               $self->{log_start} = $now;
+       }
+
+       my @bytes = unpack("C*", $data);
+
+       $self->{logfh}->print(sprintf('% 10.3f', $now - $self->{starttime}),
+               (map { sprintf(" %02x", $_) } @bytes),
+               "\n");
+
+       push @{ $self->{bytes} }, @bytes;
+       @bytes = @{ $self->{bytes} };
+
+       my @bad_bytes;
+
+       while (@bytes >= $PACKET_SIZE) {
+               if ($bytes[0] != 0x55 || $bytes[9] != 0x05
+                       || SCX::CRC::digest(@bytes[0..7]) != $bytes[8]) {
+                       push @bad_bytes, shift @bytes;
+                       next;
+               }
+
+               if (@bad_bytes) {
+                       $self->{logfh}->print("Cannot parse bytes",
+                               (map { sprintf(' %02x', $_) } @bad_bytes),
+                               "\n");
+                       @bad_bytes = ();
+               }
+
+               $self->{logfh}->print("Callback\n");
+               &{ $self->{callback} }(@bytes[1..7]);
+               splice @bytes, 0, 10;
+       }
+       if (@bad_bytes) {
+               $self->{logfh}->print("Cannot parse bytes",
+                       (map { sprintf(' %02x', $_) } @bad_bytes),
+                       "\n");
+               @bad_bytes = ();
+       }
+
+       @{ $self->{bytes} } = @bytes;
+}
+
+1;
+
diff --git a/digest b/digest
new file mode 100755 (executable)
index 0000000..95af211
--- /dev/null
+++ b/digest
@@ -0,0 +1,21 @@
+#!/usr/bin/perl -w
+
+use strict;
+use SCXCRC;
+
+my @data = (
+       # ocekavam 0x7d
+       pack("C*", 0x55, 0xff, 0xf0, 0xf0, 0xf0, 0xaa, 0xaa, 0xaa),
+
+       # ocekavam 0xb0
+       pack("C*", 0x55, 0xd6, 0x88, 0x88, 0x88, 0x14, 0x50, 0xaa),
+);
+
+for my $str (@data) {
+#      my $c = Digest::CRC->new(type=>'crc8', poly => 0x31, init=>0,
+#              xorout=>0xbb);
+#      $c->add($str);
+#      print $c->hexdigest, "\n";
+       print sprintf("%02x\n", SCXCRC::digest_str($str));
+}
+
diff --git a/ttymon b/ttymon
new file mode 100755 (executable)
index 0000000..c89dae6
--- /dev/null
+++ b/ttymon
@@ -0,0 +1,47 @@
+#!/usr/bin/perl -w
+
+use Time::HiRes qw(gettimeofday tv_interval);
+use Event::Lib;
+use SCX::Reader;
+
+my ($portname, $logfile) = @ARGV;
+
+if (!defined $portname || !defined $logfile) {
+       die "Usage: $0 /dev/ttyUSB0 logfile\n";
+}
+
+my $reader = SCX::Reader->new({
+       portname   => $portname,
+       logfile    => $logfile,
+       callback   => \&do_packet,
+});
+
+sub stdin_read {
+       my $event = shift;
+       my $fh = $event->fh;
+
+       my $data = <$fh>;
+       chomp $data;
+       print "===== ", $data, " =====\n";
+       $event->add;
+}
+
+sub tty_read {
+       my $event = shift;
+
+       $reader->read();
+       $event->add;
+}
+
+sub do_packet {
+       print "do_packet\n";
+}
+       
+my $tty_reader = event_new($reader->fh, EV_READ, \&tty_read);
+my $stdin_reader = event_new(\*STDIN, EV_READ, \&stdin_read);
+
+$tty_reader->add;
+$stdin_reader->add;
+
+event_mainloop;
+