lib/Quancom/Test/Server.pm
changeset 15 2d41fac09084
parent 14 7ccc679ac5db
child 17 ecc10b50b7a6
--- a/lib/Quancom/Test/Server.pm	Mon Jan 05 21:44:56 2009 +0100
+++ b/lib/Quancom/Test/Server.pm	Tue Jan 06 02:01:26 2009 +0100
@@ -28,7 +28,13 @@
 use IO::Socket;
 use IO::Select;
 
-my $STX = "\x02";
+my $STX   = "\x02";
+my %ERROR = (
+    checksum  => pack("ac", "E", 0),
+    character => pack("ac", "E", 1),
+    command   => pack("ac", "E", 2),
+    width     => pack("ac", "E", 3),
+);
 
 sub new {
     my $class = ref $_ ? ref shift : shift;
@@ -75,7 +81,7 @@
 
 sub show {
     my $self = shift;
-    printf STDERR "%0v8b\n", join "", @{ $self->{outputs} };
+    printf STDERR "%0v8b\n", join "", reverse @{ $self->{outputs} };
 }
 
 sub DESTROY {
@@ -117,6 +123,7 @@
                 chomp $l;
                 $l = $self->_process($l);
                 $c->print($l . "\r");
+		$self->show;
             }
         }
         return;
@@ -126,6 +133,7 @@
     while (<>) {
         chomp;
         print $self->_process($_), "\n";
+	$self->show;
     }
 }
 
@@ -140,7 +148,7 @@
 
     warn "got: <STX>$line($1)\n" if $self->{debug};
 
-    return pack("ac", "E", 1)    # checksum error
+    return $ERROR{checksum}
       if $1 ne ".." and hex($1) != unpack("%8C*", "$STX$line");
 
     my ($jid, $cmd, $width, $addr, $data) = (
@@ -155,32 +163,45 @@
 
     # some transformations for more easy use
     $addr = hex($addr);
-    $width =
-        $width eq "B" ? 1
-      : $width eq "W" ? 2
-      : $width eq "L" ? 3
-      : $width eq "X" ? 4
+    $width = $width eq "B"
+      ? 1    #  8 bit
+      : $width eq "W" ? 2    # 16 bit
+      : $width eq "L" ? 4    # 32 bit
+      : $width eq "X" ? 8    # 64 bit
       :                 0;
 
+    my @data = reverse ($data =~ /(..)/g); # msb
+    my $offset = $addr - 0x100;
+
     if ($cmd eq "W") {
-        my @data = $data =~ /(..)/g;
-        return pack("ac", "E", 3)    # width error
-          if @data != $width;
-
-        my $offset = $addr - 0x100;
+        return $ERROR{width} if @data != $width;
 
         @{ $self->{outputs} }[ $offset .. $offset + $width - 1 ] =
           map { pack "C", hex($_) } @data;
-        $self->show;
-
-        $retval = "O$jid";
-    }
-    else {
-        warn "command \"$cmd\" not supported\n";
-        $retval = pack("ac", "E", 2);
+        return _with_checksum("O$jid");
     }
 
-    return $retval . sprintf("%02x", unpack("%8C*", $retval));
+    if ($cmd =~ /^[SC]$/) {
+        # currently restricted to 4 byte (32bit)
+        return $ERROR{command} if $width != 4;
+        return $ERROR{width}   if @data != 4;
+        foreach (@{ $self->{outputs} }[ $offset .. $offset + $width - 1 ]) {
+            if ($cmd eq "S") {
+                $_ |= pack("C", hex(shift @data));
+            }
+	    else {
+		$_ &= ~pack("C", hex(shift @data));
+	    }
+        }
+        return _with_checksum("O$jid");
+    }
+
+    warn "command \"$cmd\" not supported\n";
+    return $ERROR{command};
+}
+
+sub _with_checksum {
+    $_[0] . sprintf("%02x", unpack("%8C*", $_[0]));
 }
 
 1;
@@ -215,3 +236,21 @@
 		    will be removed afterwards)
 
 =back
+
+=head1 BUGS
+
+Not all commands/registers are implemented. Currently the following
+operations are supported:
+
+=over
+
+=item B<W>
+
+Setting of outputs 0x100 .. 0x107
+
+=item B<S> and B<C>
+
+Bit-Set/Clear operations (works only on address 0x100 and 0x104) since
+it always expects 32 bit!
+
+=back