diff options
Diffstat (limited to 'kernel/xpp/calibrate_slics')
-rwxr-xr-x | kernel/xpp/calibrate_slics | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/kernel/xpp/calibrate_slics b/kernel/xpp/calibrate_slics new file mode 100755 index 0000000..c1e6064 --- /dev/null +++ b/kernel/xpp/calibrate_slics @@ -0,0 +1,308 @@ +#!/usr/bin/perl -w + +# +# $Id$ +# + +use strict; + +my $SlicsFile = "$ENV{XPP_BASE}/$ENV{XPD_BUS}/$ENV{XPD_NAME}/slics"; + +my @SlicNums = (0 .. 7); + +if ( ! -f $SlicsFile ) { + exit 1 +} + +my $debug = 0; +# set DEBUG_CALIBRATION in /etc/default/zaptel or similar +if (exists $ENV{DEBUG_CALIBRATION}) { + $debug = 1; +} + +sub mysleep($) { + my $timeout = shift; + select(undef,undef,undef,$timeout); +} + +sub logger($) { + print STDERR "LOG: @_\n"; + system("logger @_"); +} + +sub debug($) { + logger(@_) if ($debug); +} + +sub write_to_slic_file($) { + my $write_str = shift; + + open(SLICS,">$SlicsFile") or + die("Failed writing to slics file $SlicsFile"); + print SLICS $write_str; + close(SLICS); + mysleep(0.001); + +} + +sub read_reg($$$) { + my $read_slic = shift; + my $read_reg = shift; + my $direct = shift; + + write_to_slic_file( + sprintf("%d R%s %02X", $read_slic, $direct, $read_reg)); + mysleep(0.001); + open(SLICS,$SlicsFile) or + die("Failed reading from slics file $SlicsFile"); + #awk '/^SLIC_REPLY:/{print $5}' $SLICS | cut -dx -f2 + my @reply = (); + while(<SLICS>){ + #if (/^ /) { + # debug "answer line: $_"; + #} + if (/^ \d*\s+[RW][DIS]\s+[[:xdigit:]]+\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)/){ + @reply = (hex($1), hex($2)); + #debug "got [$reply]\n"; + last; + } + } + close(SLICS); + if ($direct eq 'I') { + return @reply; + } else { + return $reply[0]; + } +} + +# 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 "%d W%s %02X %02X", + $read_slic, $direct, $read_reg, $reg_val_low; + if ($direct eq 'I') { + $str .= sprintf " %02X", $reg_val_hi; + } + 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'); + } + debug($line); + } +} + +sub init_indirect_registers() { + return write_to_slic_file("# +31 WI 00 C2 55 +31 WI 01 E6 51 +31 WI 02 85 4B +31 WI 03 37 49 + +31 WI 04 33 33 +31 WI 05 02 02 +31 WI 06 02 02 +31 WI 07 98 01 + +31 WI 08 98 01 +31 WI 09 11 06 +31 WI 0A 02 02 +31 WI 0B E5 00 + +31 WI 0C 1C 0A +31 WI 0D 30 7B +31 WI 0E 63 00 +31 WI 0F 00 00 + +31 WI 10 70 78 +31 WI 11 7D 00 +31 WI 12 00 00 +31 WI 13 00 00 + +31 WI 14 F0 7E +31 WI 15 60 01 +31 WI 16 00 00 +31 WI 17 00 20 + +31 WI 18 00 20 +31 WI 19 00 00 +31 WI 1A 00 20 +31 WI 1B 00 40 + +31 WI 1C 00 10 +31 WI 1D 00 36 +31 WI 1E 00 10 +31 WI 1F 00 02 + +31 WI 20 C0 07 +31 WI 21 00 26 +31 WI 22 F4 0F +31 WI 23 00 80 + +#31 WI 24 20 03 +#31 WI 25 8C 08 +#31 WI 26 00 01 +#31 WI 27 10 00 + +31 WI 24 00 08 +31 WI 25 00 08 +31 WI 26 00 08 +31 WI 27 00 08 + +31 WI 28 00 0C +31 WI 29 00 0C +31 WI 2B 00 01 + +31 WI 63 DA 00 +31 WI 64 60 6B +31 WI 65 74 00 +31 WI 66 C0 79 + +31 WI 67 20 11 +31 WI 68 E0 3B +#"); +} + +sub init_early_direct_regs() { + return write_to_slic_file("# +31 WD 08 00 +31 WD 4A 34 +31 WD 4B 10 +31 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(31, $write_reg, 'D', 0x1F); + mysleep $ManualCalibrationSleepTime; + + # wait until all slics have finished calibration, or for timeout + while ($calibration_in_progress) { + $calibration_in_progress = 0; # until proven otherwise + my $debug_calib_str = "ManualCalib:: "; + for my $slic(@SlicNums) { + my $value = read_reg($slic, $read_reg, 'D'); + $debug_calib_str .= " [$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]); + } + } + debug($debug_calib_str); + # TODO: unnecessary sleep in the last round: + mysleep $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 + "31 WD 61 %02X\n". + "31 WD 60 %02X\n". + "", $calib_96, $calib_97 + + ); + # wait until all slics have finished calibration, or for timeout + my $sleep_cnt = 0; + # time periods in seconds: + my $sleep_time = 0.1; + my $timeout_time = 2; + CALIB_LOOP: for my $slic (@SlicNums) { + debug("checking slic $slic"); + while(1) { + if ((read_reg($slic, 60, 'D')) == 0) { + # move to next register + debug("slic $slic calibrated"); + last; + } + if ( $sleep_cnt > $timeout_time/$sleep_time) { + debug("Auto Calibration: Exiting on timeout: $timeout_time."); + last CALIB_LOOP; + } + debug("auto_calibrate not done yet: slic #$slic\n"); + mysleep(0.1); + $sleep_cnt++; + } + } + #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 (?) + +debug "starting\n"; + +init_indirect_registers(); +debug "after init_indirect_registers\n"; +init_early_direct_regs(); +debug "after init_early_direct_regs\n"; +auto_calibrate(0x47, 0x1E); +debug "after auto_calibrate\n"; +manual_calibrate(); +debug "after manul_calibrate\n"; +auto_calibrate(0x40, 0x01); +debug "after auto_calibrate 2\n"; + + |