]> jspc29.x-matter.uni-frankfurt.de Git - mvdsensorcontrol.git/commitdiff
new unpacker in devel branch
authorJan Michel <j.michel@gsi.de>
Wed, 31 Jul 2013 20:47:57 +0000 (22:47 +0200)
committerJan Michel <j.michel@gsi.de>
Wed, 31 Jul 2013 20:47:57 +0000 (22:47 +0200)
tools/preview/unpack_hld.pl [new file with mode: 0755]

diff --git a/tools/preview/unpack_hld.pl b/tools/preview/unpack_hld.pl
new file mode 100755 (executable)
index 0000000..3e53108
--- /dev/null
@@ -0,0 +1,511 @@
+#!/usr/bin/perl -w
+
+use English;
+use strict;
+use Getopt::Long;
+use Data::Dumper;
+use FileHandle;
+use feature "switch";
+
+my $SensorHeaderLength = 7;
+
+my $Statistics;
+my $PMap;
+
+
+###############################################################################
+## Configuration ##############################################################
+###############################################################################
+
+
+my $file;
+my $opt_help = 0;
+my $opt_verb = 0;
+my $opt_debug = 0;
+my $opt_frameinfo = 0;
+my $totalevents = 1E9;
+my $mode = "";
+
+GetOptions ('h|help'      => \$opt_help,
+            'f|file=s'    => \$file,
+            'v|verb'      => \$opt_verb,
+            'i|info'      => \$opt_frameinfo,
+            'd|debug'     => \$opt_debug,
+            'e|events=i'  => \$totalevents);
+
+
+
+
+if($opt_help) {
+  printf("Usage: unpack_hld.pl \n");
+  printf("[-h|--help]         Show this help\n");
+  printf("-f|--file <file>    Path to hld file\n");
+  printf("[-v|--verb]         Dump hld file content\n");
+  printf("[-i|--info]         Show frame information\n");
+  printf("[-d|--debug]        More debugging output\n");
+  printf("\n");
+  exit;
+  }
+
+
+
+###############################################################################
+## HLD Reader #################################################################
+###############################################################################
+
+
+if(&checkArgs()){
+    exit(0);
+}
+
+my @evtHeader_list = ();
+my $evtHeader_aref = \@evtHeader_list;
+
+my @subEvtHeader_list = ();
+my $subEvtHeader_aref = \@subEvtHeader_list;
+
+my @data_list = ();
+my $data_aref = \@data_list;
+
+my $fh = new FileHandle("$file", "r");
+
+while(1){
+    @evtHeader_list = ();
+
+    &getEvtHeader($fh,$evtHeader_aref);
+    &printEvtHeader($evtHeader_aref) if($opt_verb);
+
+    my $evtSize = $evtHeader_aref->[0];
+    if (!defined $evtSize || $evtSize < 0x10) {last;}
+
+    #- If the size is only 32 Bytes -> goto to 
+    #  the next Event Header since there are no subevents
+    next unless defined $evtSize;
+    next if($evtSize == 32);
+
+    my $size_cntr = 32;  # Bytes
+
+    while($evtSize > $size_cntr){
+
+        @subEvtHeader_list = ();
+
+        my $decoding = &getSubEvtHeader($fh,$subEvtHeader_aref);
+        &printSubEvtHeader($subEvtHeader_aref) if($opt_verb);
+
+        my $subEvtSize = $subEvtHeader_aref->[0];
+
+        $size_cntr = $size_cntr + $subEvtSize;
+
+        #- If the size is only 16 Bytes -> goto to 
+        #  the next Sub Event Header since there are no subevents
+        next if($subEvtSize == 16);
+
+        @data_list = ();
+        &getSubEvtData($fh, $data_aref, $subEvtSize, $decoding);
+        &printData($data_aref) if($opt_verb);
+
+        my $paddedSize = &padding($fh, $subEvtSize);
+
+        $size_cntr = $size_cntr + $paddedSize;
+
+        #----------> User function <---------
+        &analyzeData($evtHeader_aref, $subEvtHeader_aref, $data_aref);
+    }
+}
+
+WriteResults();
+
+$fh->close();
+
+exit(0);
+
+####################### END OF MAIN ###################
+
+sub printEvtHeader()
+{
+    my ($data_aref) = @_;
+
+    print "\n";
+
+    printf("size: %08x    ", $data_aref->[0]);
+    printf("decoding: %08x  ", $data_aref->[1]);
+    printf("id:    %08x  ", $data_aref->[2]);
+    printf("seqNr:  %08x\n", $data_aref->[3]);
+
+    my $year = (($data_aref->[4] >> 16) & 0xff) + 1900;
+    my $mon  = (($data_aref->[4] >> 8) & 0xff) + 1;
+    my $mday = ($data_aref->[4] >> 0) & 0xff;
+
+    my $hour = ($data_aref->[5] >> 16) & 0xff;
+    my $min  = ($data_aref->[5] >> 8) & 0xff;
+    my $sec  = ($data_aref->[5] >> 0) & 0xff;
+
+    printf("date: %04d-%02d-%02d  ", $year, $mon, $mday);
+    printf("time:     %02d:%02d:%02d  ", $hour, $min, $sec);
+    printf("runNr: %08x  ", $data_aref->[6]);
+    printf("expId:  %08x\n", $data_aref->[7]);    
+}
+
+sub printSubEvtHeader()
+{
+    my ($data_aref) = @_;
+
+    print "\n";
+
+    printf("size: %08x    ", $data_aref->[0]);
+    printf("decoding: %08x  ", $data_aref->[1]);
+    printf("id:    %08x  ", $data_aref->[2]);
+    printf("trigNr: %08x\n", $data_aref->[3]);
+}
+
+sub printData()
+{
+    my ($data_aref) = @_;
+
+    my $cntr = 0;
+
+    print "\n";
+
+    foreach my $word (@$data_aref){
+        printf("%08x ", $word);
+        
+        $cntr++;
+        
+        print "\n" if( ($cntr%4) == 0);
+    }
+}
+
+sub getEvtHeader()
+{
+    my ($fh, $data_aref) = @_;
+
+    my @tmp_list;
+
+    foreach my $i (1..8){
+        my $header;
+
+        read($fh, $header, 4);
+        &checkEndOfFile($fh, $header);
+
+        push(@tmp_list, $header);
+    }
+
+    my $decoding = unpack("V*", $tmp_list[1]);
+    unless(defined $decoding) {
+      printf "This seems to be the end\n" if $opt_verb; 
+      return -1;
+      }
+    
+    if($opt_debug){
+        if(&getEndianess($decoding)){  
+            printf("\n Event Decoding: %08x   Byte Order: Little Endian\n", $decoding);
+        }
+        else{
+            printf("\n Event Decoding: %08x   Byte Order: Big Endian\n", $decoding);
+        }
+    }
+
+    foreach my $tmp (@tmp_list){
+        my $word;
+
+        if(&getEndianess($decoding)){
+            $word = unpack("V*", $tmp);  # Small Endian
+        }
+        else{
+            $word = unpack("N*", $tmp);  # Big Endian
+        }
+        
+        push(@$data_aref, $word);
+    }
+}
+
+sub getSubEvtHeader()
+{
+    my ($fh, $data_aref) = @_;
+
+    my @tmp_list;
+
+    foreach my $i (1..4){
+        my $header;
+        
+        read($fh, $header, 4);
+        &checkEndOfFile($fh, $header);
+
+        push(@tmp_list, $header);
+    }
+
+    my $decoding = unpack("V*", $tmp_list[1]);
+
+    if($opt_debug){
+        if(&getEndianess($decoding)){
+            printf("\n SubEvent Decoding: %08x   Byte Order: Little Endian\n", $decoding);
+        }
+        else{      
+            printf("\n SubEvent Decoding: %08x   Byte Order: Big Endian\n", $decoding);
+        }
+    }    
+
+    foreach my $tmp (@tmp_list){
+        my $word;
+
+        if(&getEndianess($decoding)){
+            $word = unpack("V*", $tmp);  # Small Endian
+        }
+        else{
+            $word = unpack("N*", $tmp);  # Big Endian
+        }
+        
+        push(@$data_aref, $word);
+    }
+
+    return &getEndianess($decoding);
+}
+
+sub getEndianess()
+{
+    my ($decoding) = @_;
+
+    # Return values:
+    # 0 : Big Endian
+    # 1 : Little Endian
+    #
+    # Usually (when sent by GbE-FPGAs) Event Headers are Little Endian
+    # SubEvent Headers and data are Big Endian
+
+    my $retVal = 0;
+
+    if(defined($decoding) && ($decoding & 0x000000ff) > 0){
+        $retVal = 1;  # This is Little Endian
+    }
+
+    return $retVal;
+}
+
+sub getSubEvtData()
+{
+    my ($fh, $data_aref, $size, $decoding) = @_;
+
+    #- Subtract subevent header size and devide by word size
+    my $nrOfWords = ($size - 16)/4;
+
+    foreach my $i (1..$nrOfWords){
+
+        my $tmp;
+        read($fh, $tmp, 4);
+        &checkEndOfFile($fh, $tmp);
+
+            my $word;
+
+        if(&getEndianess($decoding)){
+            $word = unpack("V*", $tmp);  # Little Endian
+        }
+        else{
+            $word = unpack("N*", $tmp);  # Big Endian
+        }
+
+        push(@$data_aref, $word);
+    }    
+}
+
+sub padding()
+{
+    my ($fh, $size) = @_;
+
+    my $retVal = 0;  # Size of the padded word
+
+    #- Check 64-bit (8-Byte) alignment
+    unless( ($size%8) == 0){
+        my $tmp;
+        read($fh, $tmp, 4);
+
+        my $word;
+        $word = unpack("V*", $tmp);  # Little Endian
+
+        unless($word == 0){
+            #- Padding word is not zero
+
+            printf("\n Padding word is not zero: %08x! \n", $word) if($opt_debug);
+            #$fh->close();
+            #exit(0);
+        }
+
+        $retVal = 4;  # Bytes
+    }
+
+    return $retVal;
+}
+
+sub checkEndOfFile()
+{
+    my ($fh, $tmp) = @_;
+
+    unless( defined $tmp){
+        #- The end of the file
+        print "\n End of file\n";
+        $fh->close();
+        exit(0);
+    }
+}
+
+sub checkArgs()
+{
+    my $retVal = 0;
+
+    unless( defined $file){
+        print "\n You must provide a path to the hld file!\n";
+        print " Read help.\n";
+        $retVal = 1;
+    }
+
+    return $retVal;
+}
+
+
+
+
+
+
+
+###############################################################################
+## MVD Unpacker ###############################################################
+###############################################################################
+
+
+
+sub analyzeData() {
+  my ($evtHeader, $subEvtHeader, $data) = @_;
+  my $EvtId = $evtHeader->[3];
+  my $pos = 0;
+  my $time = 0;
+  my $SubEvtSize =  $subEvtHeader->[1]/4-6;
+  
+  SSELoop: while(1) { #Loop over SubSubEvents
+  
+    #Read SubSubEvent Header
+    my $RocId      = $data->[$pos] & 0xffff;
+    my $RocLength  = ($data->[$pos]>>16) & 0xffff;
+    if($RocId == 0x5555) {last;}
+    my $RocEnd = $pos + $RocLength;
+    $pos++;
+    
+    SensLoop: while(1) { #Loop over Sensors
+      #Read Sensor Header
+      my $SensorHead   = $data->[$pos++];
+      my $SensorId     = $data->[$pos++] & 0xffff;
+      my $SensorStatus = $data->[$pos++];
+      my $SensorError  = $data->[$pos++];
+      my $SensorDebug  = $data->[$pos++];
+      my $SensorTime   = sprintf("%08x%08x",$data->[$pos+1],$data->[$pos]);
+      $pos+= 2;
+      
+      printf("ID\t%8x\tStatus\t%08x\tError\t%08x\tDebug\t%08x\tTime\t%s\n",
+              $SensorId, $SensorStatus, $SensorError, $SensorDebug, $SensorTime)   if $opt_frameinfo;
+      
+      #Could it be...?
+      if($SensorHead != 0xffffffff) {
+        #Something is really wrong with data. Skip SubEvent!
+        printf("Broken Sensor Header\n") if $opt_frameinfo;
+        $Statistics->{$SensorId}->{Broken}++;
+        last SSELoop;
+        }
+        
+      #Check Status Word
+      my $SensorIsValid = 0;
+      if($SensorStatus == 0xf000000f) {
+        $SensorIsValid = 1;
+        $Statistics->{$SensorId}->{Valid}++;
+        }
+      else {
+        $SensorIsValid = 0;
+        $Statistics->{$SensorId}->{Broken}++;
+        }
+
+      if($SensorIsValid){
+        #Hey Sensor, tell me who you are!
+        my $SensorDummy  = $data->[$pos++];
+        my $SensorNumber = $data->[$pos++];
+        my $SensorLength = $data->[$pos++] & 0xffff;
+        
+        printf("\t\t\tHeader\t%08x\tFrame\t%08x\tLength\t%i\n",
+                $SensorDummy, $SensorNumber, $SensorLength)  if $opt_frameinfo;
+
+        my $FrameEndPos = $pos + $SensorLength;
+        my ($i, $d, $line, $column, $pixels, $statecnt, $ovf) = (0,0,0,0,0,0,0);
+        while(1) {
+          #Disentangle 16 Bit words
+          if($i++%2) {$d = $data->[$pos++] & 0xffff;}
+          else       {$d = ($data->[$pos] >> 16) & 0xffff;}
+          
+          #Is new line?
+          if($statecnt-- == 0) {
+            $ovf      += $d >> 15;
+            $line      = ($d >> 4) & 0x7FF;
+            $statecnt  = $d & 0xF;
+            }
+          else {
+            $pixels = ($d & 0x3) + 1;
+            $column = ($d >> 2) & 0x7FF;
+            printf("\t$line, $column x $pixels\n") if $opt_frameinfo;
+            
+            $PMap->{$SensorId}->[$line]->[$column]++;
+            $PMap->{$SensorId}->[$line]->[$column+1]++ if $pixels > 1;
+            $PMap->{$SensorId}->[$line]->[$column+2]++ if $pixels > 2;
+            $PMap->{$SensorId}->[$line]->[$column+3]++ if $pixels > 3;
+            }
+          
+          last if $pos >= $FrameEndPos;
+          }
+        
+        
+        #Read end of frame marker without check
+        $pos++; 
+        }
+      if($pos >= $RocEnd){
+        last SensLoop;
+        }
+      }
+    }
+  }
+  
+  
+sub WriteResults {
+
+
+  foreach my $id (keys $Statistics) {
+    #No frames? No plot!
+    if(!defined $Statistics->{$id}->{Valid}) {next;}
+    
+    my $fn = "gnuplot";
+    $fh = new FileHandle ("|$fn") or  die "error: no gnuplot";
+    $fh->autoflush(1);
+
+    print $fh  "set terminal pngcairo;\n";
+    print $fh  "set palette model RGB;\n";
+    print $fh  "set xrange [0:1152];\n";
+    print $fh  "set yrange [0:576];\n";
+    print $fh  "set cbrange [0:20000];\n";
+    print $fh  "set palette defined ( 0 'white', 1 'red', 5 'black', 10 'blue', 20000 'green');\n";
+    my $s = sprintf("%04x",$id);
+    print $fh  "set output './image_recalibrated_$s.png';\n";
+    print $fh  "plot '-' matrix with image\n";
+
+
+    for(my $y = 0; $y < 576; $y++) {
+      my $l = "";
+      for(my $x = 0; $x < 1152; $x++) {
+        if (defined $PMap->{$id}->[$y]->[$x]) {
+          $l .= $PMap->{$id}->[$y]->[$x]." " ;
+          }
+        else {
+          $l .= "0 ";
+          }
+        }
+      print $fh $l."\n";
+      }
+    print $fh "e\nexit\n";
+    $fh->close();
+    }
+    
+
+  }
+