From: Jan Michel Date: Wed, 31 Jul 2013 20:47:57 +0000 (+0200) Subject: new unpacker in devel branch X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=fdac040f38b4e237c9d82120431cae7772b5467d;p=mvdsensorcontrol.git new unpacker in devel branch --- diff --git a/tools/preview/unpack_hld.pl b/tools/preview/unpack_hld.pl new file mode 100755 index 0000000..3e53108 --- /dev/null +++ b/tools/preview/unpack_hld.pl @@ -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 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(); + } + + + } +