From 8eeb67728cc1db4007233f862c61376a094c9d41 Mon Sep 17 00:00:00 2001 From: tzafrir Date: Tue, 13 May 2008 20:01:23 +0000 Subject: xpp r5723: Includes, among others: * New firmware protocol version: 3.0 . * New numbers for the device types: (e.g. in card_init* scripts) - FXS: 1 (was: 3) - FXO: 2 (was: 4) - BRI: 3 (was: 6 for TE, 7 for NT) - PRI: 4 (was: 9) * Init scripts of FXS and FXO modules are now written in Perl as well (be sure to have File::Basename, e.g: perl-modules in Debian). * calibrate_slics merged into init_card_1_30 . * Module parameter print_dbg replaced with debug . Same meaning. * init_fxo_modes removed: content moved into init_card_2_30, verified at build time. * Code tested with sparse. Most warnings were fixed. * Set ZT_SIG_DACS for the bchans in the PRI and BRI modules to not get ignored by ztscan. * Handle null config_desc we get from some crazy USB controllers. * genzaptelconf: Fix reporting of empty slots in list mode. * xpp_blink can now blink a single analog port. * "slics" has been renamed "chipregs". * Fixed a small typo in fpga_load(8). * Fixed bashism in xpp_fxloader. git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.2@4264 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- xpp/init_card_1_30 | 535 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 535 insertions(+) create mode 100755 xpp/init_card_1_30 (limited to 'xpp/init_card_1_30') diff --git a/xpp/init_card_1_30 b/xpp/init_card_1_30 new file mode 100755 index 0000000..68a6d02 --- /dev/null +++ b/xpp/init_card_1_30 @@ -0,0 +1,535 @@ +#! /usr/bin/perl -w +use strict; + +# +# Written by Oron Peled +# Copyright (C) 2006, Xorcom +# +# All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# See the file LICENSE in the top level of this tarball. +# + +# +# $Id$ +# +# Data format: +# - A comment start with ';' or '#' until the end of line +# - Blank lines are ignored +# - Fields are whitespace separated (spaces or tabs) +# +# The fields are (in command line order): +# 1. SLIC select in decimal (range 0-7). +# * is a special value which means ALL SLICS (only some registers +# accept settings for ALL SLICS). +# 2. Command word: +# - RD Read Direct register. +# - RI Read Indirect register. +# - WD Write Direct register. +# - WI Write Indirect register. +# 3. Register number in hexadecimal. +# 4. Low data byte in hexadecimal. (for WD and WI commands). +# 5. High data byte in hexadecimal. (for WI command only). +# +# + +package main; +use File::Basename; +use Getopt::Std; + +my $program = basename("$0"); +my $init_dir = dirname("$0"); +BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir", "$init_dir/zconf"); } +use Zaptel::Config::Defaults; +my $unit_id; +my %opts; +$ENV{XPP_BASE} = '/proc/xpp'; + +getopts('o:', \%opts); + +my $debug; +my $skip_calib; + +my $xpd_name = sprintf("XPD-%1d0", $ENV{UNIT_NUMBER}); +my $chipregs = "$ENV{XPP_BASE}/$ENV{XBUS_NAME}/$xpd_name/chipregs"; + +sub logit { + print STDERR "$unit_id: @_\n"; +} + +sub debug { + logit @_ if $debug; +} + +# Arrange for error logging +if (-t STDERR) { + $unit_id = 'Interactive'; + logit "Interactive startup"; +} else { + $unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}"; + open (STDERR, "| logger -t $program -p kern.info") || die; + logit "Non Interactive startup"; +} + +sub set_output() { + my $output; + + if($opts{o}) { + $output = $opts{o}; + } else { + # No subunits in FXS (everything is subunit 0) + $output = $chipregs; + } + open(REG, ">$output") || die "Failed to open '$output': $!\n"; + my $oldfh = select REG; + print "# Setting output\n" if $opts{o}; + return $oldfh; +} + +sub mysleep($) { + my $timeout = shift; + select(undef,undef,undef,$timeout); +} + +package FXS; + +sub gen { + my $fmt = shift; + $| = 1; + printf "$fmt\n", @_; +} + +my @SlicNums = (0 .. 7); + +sub write_to_slic_file($) { + my $write_str = shift; + + open(SLICS,">$chipregs") or + die("Failed writing to chipregs file $chipregs"); + print SLICS $write_str; + close(SLICS) or die "Failed writing '$write_str' to '$chipregs': $!"; + main::mysleep(0.001); + +} + +sub read_reg($$$) { + my $read_slic = shift; + my $read_reg = shift; + my $direct = shift; + + write_to_slic_file( + sprintf("%s R%s %02X", $read_slic, $direct, $read_reg)); + main::mysleep(0.005); + open(SLICS,$chipregs) or + die("Failed reading from chipregs file $chipregs"); + #awk '/^SLIC_REPLY:/{print $5}' $SLICS | cut -dx -f2 + my @reply = (); + while(){ + #if (/^ /) { + # main::debug "answer line: $_"; + #} + s/#.*//; + next unless /\S/; + if (/^ \d*\s+[RW][DI]\s+[[:xdigit:]]+\s+([[:xdigit:]]+)\s+([[:xdigit:]]*)/){ + @reply = (hex($1), hex($2)); + #main::debug "got [$reply]"; + last; + } else { + main::logit("Got from '$chipregs' a non-matching line '$_'"); + } + } + close(SLICS); + die("Failed reading from '$chipregs' ($read_slic,$read_reg,$direct)") + unless @reply; + 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 "%s 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'); + } + main::debug($line); + } +} + +sub init_indirect_registers() { + return write_to_slic_file("# +* WI 1E 00 C2 55 +* WI 1E 01 E6 51 +* WI 1E 02 85 4B +* WI 1E 03 37 49 + +* WI 1E 04 33 33 +* WI 1E 05 02 02 +* WI 1E 06 02 02 +* WI 1E 07 98 01 + +* WI 1E 08 98 01 +* WI 1E 09 11 06 +* WI 1E 0A 02 02 +* WI 1E 0B E5 00 + +* WI 1E 0C 1C 0A +* WI 1E 0D 30 7B +* WI 1E 0E 63 00 +* WI 1E 0F 00 00 + +* WI 1E 10 70 78 +* WI 1E 11 7D 00 +* WI 1E 12 00 00 +* WI 1E 13 00 00 + +* WI 1E 14 F0 7E +* WI 1E 15 C0 01 +* WI 1E 16 00 00 +* WI 1E 17 00 20 + +* WI 1E 18 00 20 +* WI 1E 19 00 00 +* WI 1E 1A 00 20 +* WI 1E 1B 00 40 + +* WI 1E 1C 00 10 +* WI 1E 1D 00 36 +* WI 1E 1E 00 10 +* WI 1E 1F 00 02 + +* WI 1E 20 C0 07 +* WI 1E 21 00 26 +* WI 1E 22 F4 0F +* WI 1E 23 00 80 + +#* WI 1E 24 20 03 +#* WI 1E 25 8C 08 +#* WI 1E 26 00 01 +#* WI 1E 27 10 00 + +* WI 1E 24 00 08 +* WI 1E 25 00 08 +* WI 1E 26 00 08 +* WI 1E 27 00 08 + +* WI 1E 28 00 0C +* WI 1E 29 00 0C +* WI 1E 2B 00 01 + +* WI 1E 63 DA 00 +* WI 1E 64 60 6B +* WI 1E 65 74 00 +* WI 1E 66 C0 79 + +* WI 1E 67 20 11 +* WI 1E 68 E0 3B +#"); +} + +sub init_early_direct_regs() { + return write_to_slic_file("# +* WD 08 00 # Audio Path Loopback Control +* WD 4A 34 # High Battery Voltage +* WD 4B 10 # Low Battery Voltage +* WD 40 00 # Line Feed Control +#") +} + +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('*', $write_reg, 'D', 0x1F); + main::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]); + } + } + main::debug($debug_calib_str); + # TODO: unnecessary sleep in the last round: + main::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 + "* WD 60 %02X\n". + "* WD 61 %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) { + main::debug("checking slic $slic"); + while(1) { + if ((read_reg($slic, 60, 'D')) == 0) { + # move to next register + main::debug("slic $slic calibrated"); + last; + } + if ( $sleep_cnt > $timeout_time/$sleep_time) { + main::debug("Auto Calibration: Exiting on timeout: $timeout_time."); + last CALIB_LOOP; + } + main::debug("auto_calibrate not done yet: slic #$slic"); + main::mysleep(0.1); + $sleep_cnt++; + } + } + #log_calib_params(); +} + +sub calibrate_slics() { + main::logit "Calibrating '$0'"; + auto_calibrate(0x47, 0x1E); + main::debug "after auto_calibrate"; + manual_calibrate(); + main::debug "after manul_calibrate"; + auto_calibrate(0x40, 0x01); + main::debug "after auto_calibrate 2"; + main::logit "Continue '$0'"; +} + +sub read_defaults() { + # For lab tests + my $labfile = "$init_dir/genzaptelconf.env"; + + # Source default files + $ENV{ZAPTEL_DEFAULTS} = "$labfile" if -r "$labfile"; + my $var_debug = 'DEBUG_INIT_FXS'; + my $var_skip_calib = 'INIT_FXS_SKIP_CALIB'; + my ($default_file, %source_defaults) = + Zaptel::Config::Defaults::source_vars($var_debug, $var_skip_calib); + $debug = $source_defaults{$var_debug}; + $skip_calib = $source_defaults{$var_skip_calib}; + main::logit "From $default_file: $var_debug=$debug $var_skip_calib=$skip_calib"; +} + +package main; + +main::logit "Starting '$0'"; + +FXS::read_defaults; +main::debug "before init_indirect_registers"; +FXS::init_indirect_registers(); +main::debug "after init_indirect_registers"; +FXS::init_early_direct_regs(); +main::debug "after init_early_direct_regs"; +if($skip_calib) { + main::logit "==== WARNING: SKIPPED SLIC CALIBRATION ====="; +} else { + FXS::calibrate_slics; +} +set_output; +while() { + chomp; + s/[#;].*$//; # remove comments + s/^\s+//; # trim whitespace + s/\s+$//; # trim whitespace + s/\t+/ /g; # replace tabs with spaces (for logs) + next unless /\S/; # Skip empty lines + main::debug "writing: '$_'"; + print "$_\n"; +} +close REG; + +main::logit "Ending '$0'"; +close STDERR; +exit 0; + +# ----------------------------------==== 8-channel FXS unit initialization ===----------------------------------------- + +__DATA__ +# Change SLICs states to "Open state"s (Off,all transfers tristated to avoid data collision), Voltage sense +* WD 40 00 + +# Flush out energy accumulators +* WI 1E 58 00 00 +* WI 1E 59 00 00 +* WI 1E 5A 00 00 +* WI 1E 5B 00 00 +* WI 1E 5C 00 00 +* WI 1E 5D 00 00 +* WI 1E 5E 00 00 +* WI 1E 5F 00 00 +* WI 1E 61 00 00 +* WI 1E 58 00 00 +* WI 1E C1 00 00 +* WI 1E C2 00 00 +* WI 1E C3 00 00 +* WI 1E C4 00 00 +* WI 1E C5 00 00 +* WI 1E C6 00 00 +* WI 1E C7 00 00 +* WI 1E C8 00 00 +* WI 1E C9 00 00 +* WI 1E CA 00 00 +* WI 1E CB 00 00 +* WI 1E CC 00 00 +* WI 1E CD 00 00 +* WI 1E CE 00 00 +* WI 1E CF 00 00 +* WI 1E D0 00 00 +* WI 1E D1 00 00 +* WI 1E D2 00 00 +* WI 1E D3 00 00 + +# Setting of SLICs offsets +# New card initialization +0 WD 02 00 +0 WD 04 00 +1 WD 02 08 +1 WD 04 08 +2 WD 02 10 +2 WD 04 10 +3 WD 02 18 +3 WD 04 18 +4 WD 02 20 +4 WD 04 20 +5 WD 02 28 +5 WD 04 28 +6 WD 02 30 +6 WD 04 30 +7 WD 02 38 +7 WD 04 38 +* WD 03 00 +* WD 05 00 + +# Audio path. (also initialize 0A and 0B here if necessary) +* WD 08 00 +* WD 09 C0 + +# Automatic/Manual Control: defaults but: +# Cancel AOPN - Power Alarm +# Cancel ABAT - Battery Feed Automatic Select +* WD 43 16 + +# Loop Closure Debounce Interval +* WD 45 0A + +# Ring Detect Debounce Interval +* WD 46 47 + +# Battery Feed Control: Battery low (DCSW low) +* WD 42 00 + +# Loop Current Limit +* WD 47 00 + +# Ring VBath: +* WD 4A 3F + + +* WD 6C 01 + +* WI 1E 23 00 80 +* WI 1E 24 20 03 +* WI 1E 25 8C 08 +* WI 1E 26 00 01 +* WI 1E 27 10 00 + +#------ Metering tone +* WI 1E 17 61 15 # Amplitue Ramp-up +* WI 1E 18 61 15 # Max Amplitude +* WI 1E 19 FB 30 # Frequency +* WD 2C 00 # Timer dL +* WD 2D 03 # Timer dH + +# ------------------------------------- Initialization of direct registers -------------------------------------------- + +# Mode(8-bit,u-Law,1 PCLK ) setting, Loopbacks and Interrupts clear + +* WD 01 29 +#* WD 0E 00 + +#* WD 15 00 +#* WD 16 03 + +# Clear pending interrupts +* WD 12 FF +* WD 13 FF +* WD 14 FF + +#* WD 4A 34 +#* WD 4B 10 -- cgit v1.2.3