#!/usr/bin/perl -w # # $Id:$ # use strict; use Time::HiRes qw (time alarm sleep); my $SlicsFile = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics"; my @SlicNums = (0 .. 7); if ( ! -f $SlicsFile ) { exit 1 } sub logger($) { print STDERR "LOG: @_\n"; system("logger @_"); } sub write_to_slic_file($) { my $write_str = shift; #print STDERR "[Writing string]\n".$write_str."[End String]\n"; open(SLICS,">$SlicsFile") or die("Failed writing to slics file $SlicsFile"); print SLICS $write_str; close(SLICS); sleep(0.001); } sub read_reg($$$) { my $read_slic = shift; my $read_reg = shift; my $direct = shift; write_to_slic_file( sprintf("%02x 00 00 00 R%s %02X", 1<<$read_slic, $direct, $read_reg)); sleep(0.001); open(SLICS,$SlicsFile) or die("Failed reading from slics file $SlicsFile"); my @reply = (); while(){ #if (/^[^#]/) { # print STDERR "answer line: $_"; #} if (/^SLIC_REPLY:\s+[DI]\s+reg_num=0x[[:xdigit:]]+,\s+dataH=0x([[:xdigit:]]+)\s+dataL=0x([[:xdigit:]]+)/){ @reply = (hex($1), hex($2)); #print STDERR "got [@reply]\n"; last; } } close(SLICS); if ($direct eq 'I') { return @reply; } else { return $reply[1]; } } # TODO: rearange arguments sub write_reg{#($$$$$) { my $read_slic = shift; my $read_reg = shift; my $direct = shift; my $reg_val_low = shift; my $reg_val_hi = shift; my $str = sprintf "%02x 00 00 00 W%s %02X %02X", 1<<$read_slic, $direct, $read_reg, $reg_val_low; if ($direct eq 'I') { $str .= sprintf " %02X", $reg_val_hi; } #printf STDERR "Writing: $str\n"; write_to_slic_file($str); } # TODO: rearange arguments sub write_reg_all_slics{#($$$$) { my $read_reg = shift; my $direct = shift; my $reg_val_low = shift; my $reg_val_hi = shift; my $str = sprintf "FF FF 00 00 W%s %02X %02X", $direct, $read_reg, $reg_val_low; if ($direct eq 'I') { $str .= sprintf " %02X", $reg_val_hi; } printf STDERR "Writing: $str\n"; write_to_slic_file($str); } sub log_calib_params() { for my $i (100 .. 107) { my $line="Calib Reg $i: "; for my $slic (@SlicNums) { $line .= " ".read_reg($slic, $i, 'D'); } logger($line); } } sub init_indirect_registers() { return write_to_slic_file("# FF FF 00 00 WI 00 C2 55 FF FF 00 00 WI 01 E6 51 FF FF 00 00 WI 02 85 4B FF FF 00 00 WI 03 37 49 FF FF 00 00 WI 04 33 33 FF FF 00 00 WI 05 02 02 FF FF 00 00 WI 06 02 02 FF FF 00 00 WI 07 98 01 FF FF 00 00 WI 08 98 01 FF FF 00 00 WI 09 11 06 FF FF 00 00 WI 0A 02 02 FF FF 00 00 WI 0B E5 00 FF FF 00 00 WI 0C 1C 0A FF FF 00 00 WI 0D 30 7B FF FF 00 00 WI 0E 63 00 FF FF 00 00 WI 0F 00 00 FF FF 00 00 WI 10 70 78 FF FF 00 00 WI 11 7D 00 FF FF 00 00 WI 12 00 00 FF FF 00 00 WI 13 00 00 FF FF 00 00 WI 14 F0 7E FF FF 00 00 WI 15 60 01 FF FF 00 00 WI 16 00 00 FF FF 00 00 WI 17 00 20 FF FF 00 00 WI 18 00 20 FF FF 00 00 WI 19 00 00 FF FF 00 00 WI 1A 00 20 FF FF 00 00 WI 1B 00 40 FF FF 00 00 WI 1C 00 10 FF FF 00 00 WI 1D 00 36 FF FF 00 00 WI 1E 00 10 FF FF 00 00 WI 1F 00 02 FF FF 00 00 WI 20 C0 07 FF FF 00 00 WI 21 00 26 FF FF 00 00 WI 22 F4 0F FF FF 00 00 WI 23 00 80 #FF FF 00 00 WI 24 20 03 #FF FF 00 00 WI 25 8C 08 #FF FF 00 00 WI 26 00 01 #FF FF 00 00 WI 27 10 00 FF FF 00 00 WI 24 00 08 FF FF 00 00 WI 25 00 08 FF FF 00 00 WI 26 00 08 FF FF 00 00 WI 27 00 08 FF FF 00 00 WI 28 00 0C FF FF 00 00 WI 29 00 0C FF FF 00 00 WI 2B 00 01 FF FF 00 00 WI 63 DA 00 FF FF 00 00 WI 64 60 6B FF FF 00 00 WI 65 74 00 FF FF 00 00 WI 66 C0 79 FF FF 00 00 WI 67 20 11 FF FF 00 00 WI 68 E0 3B #"); } sub init_early_direct_regs() { return write_to_slic_file("# FF FF 00 00 WD 08 00 FF FF 00 00 WD 4A 34 FF FF 00 00 WD 4B 10 FF FF 00 00 WD 40 00 #") } my @FilterParams = (); sub save_indirect_filter_params() { for my $slic (@SlicNums) { for my $reg (35 .. 39) { $FilterParams[$slic][$reg] = [read_reg($slic, $reg, 'I')]; write_reg($slic, $reg, 'I', 0, 0x80); } } } sub restore_indirect_filter_params() { for my $slic (@SlicNums) { for my $reg (35 .. 39) { write_reg($slic, $reg, 'I', @{$FilterParams[$slic][$reg]}); } } } my $ManualCalibrationSleepTime = 0.04; # 40ms sub manual_calibrate_loop($$) { my $write_reg = shift; my $read_reg = shift; # counters to count down to (at most) 0 my @slic_counters = (); for my $i (0 .. $#SlicNums) { $slic_counters[$i] = 0x1F; } # start calibration: my $calibration_in_progress = 1; write_reg_all_slics($write_reg, 'D', 0x1F); sleep $ManualCalibrationSleepTime; # wait until all slics have finished calibration, or for timeout while ($calibration_in_progress) { $calibration_in_progress = 0; # until proven otherwise print STDERR "ManualCalib:: "; for my $slic(@SlicNums) { my $value = read_reg($slic, $read_reg, 'D'); print STDERR " [$slic_counters[$slic]:$value]"; if ($value != 0 && $slic_counters[$slic] >= 0) { $calibration_in_progress = 1; $slic_counters[$slic]--; write_reg($slic,$write_reg,'D',$slic_counters[$slic]); } } print STDERR "\n"; # TODO: unnecessary sleep in the last round: sleep $ManualCalibrationSleepTime; } } sub manual_calibrate() { manual_calibrate_loop(98, 88); manual_calibrate_loop(99, 89); } sub auto_calibrate($$) { my $calib_96 = shift; my $calib_97 = shift; #log_calib_params(); # start calibration: write_to_slic_file( sprintf "FF FF 00 00 WD 61 %02X\n". "FF FF 00 00 WD 60 %02X\n". "", $calib_97, $calib_96 ); # wait until all slics have finished calibration, or for timeout my $end_time=time() + 2; my $timeout=0; CALIB_LOOP: for my $slic (@SlicNums) { logger("checking slic $slic"); while(1) { my $reply; if (($reply=read_reg($slic, 96, 'D')) == 0) { # move to next register logger("slic $slic calibrated"); last; } print STDERR "reply: $reply\n"; my $time=time(); if ( $time > $end_time) { $timeout=1; logger("Exiting on timeout: $time is after timeout $end_time ."); exit 1; #last CALIB_LOOP; } logger("auto_calibrate not done yet: slic #$slic\n"); sleep(0.1); } } #log_calib_params(); } ########################################################### # # main # # TODO: for all slics check the following reads to check communication #read_reg($slic, 0x08, 'D'): 0x02 #read_reg($slic, 0x0B, 'D'): 0x33 #read_reg($slic, 0x40, 'D'): 0x00 (?) print STDERR "starting\n"; init_indirect_registers(); print STDERR "after init_indirect_registers\n"; init_early_direct_regs(); print STDERR "after init_early_direct_regs\n"; auto_calibrate(0x47, 0x1E); print STDERR "after auto_calibrate\n"; manual_calibrate(); print STDERR "after manul_calibrate\n"; auto_calibrate(0x40, 0x01); print STDERR "after auto_calibrate 2\n";