summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2009-04-16 19:35:48 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2009-04-16 19:35:48 +0000
commitdbcc980b4c26c82e54347d70b58fdd58a4bdceef (patch)
tree6f51e3736e7403faa77ff163602df40d008b7015
parente3429f060d5d3443f1b65c654fad2f145b88a10b (diff)
xpp fxs/fxo: PCM and DTMF fixes
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@6393 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-rw-r--r--drivers/dahdi/xpp/card_fxs.c8
-rwxr-xr-xdrivers/dahdi/xpp/init_card_1_30268
-rwxr-xr-xdrivers/dahdi/xpp/init_card_2_3029
3 files changed, 169 insertions, 136 deletions
diff --git a/drivers/dahdi/xpp/card_fxs.c b/drivers/dahdi/xpp/card_fxs.c
index 56fe89e..7171f9b 100644
--- a/drivers/dahdi/xpp/card_fxs.c
+++ b/drivers/dahdi/xpp/card_fxs.c
@@ -568,7 +568,6 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, bool msg_waiting)
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0xEF, 0x7B);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0x9F, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x19);
- ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0xE0);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x01);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0xF0);
@@ -577,11 +576,12 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos, bool msg_waiting)
} else {
/* A write to register 0x40 will now turn on/off the ringer */
LINE_DBG(SIGNAL, xpd, pos, "RINGER\n");
+
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16, 0x00, 0x00);
- ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0x60, 0x01);
- ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0xF0, 0x7E);
+ ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15, 0x77, 0x01);
+ ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14, 0xFD, 0x7E);
+
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x00);
- ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0x00);
diff --git a/drivers/dahdi/xpp/init_card_1_30 b/drivers/dahdi/xpp/init_card_1_30
index 1356847..c0e2410 100755
--- a/drivers/dahdi/xpp/init_card_1_30
+++ b/drivers/dahdi/xpp/init_card_1_30
@@ -148,28 +148,45 @@ sub read_reg($$$) {
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(<SLICS>){
- #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 '$_'");
+ my $retries = 10;
+ my @reply;
+ # If the command queue is long, we may need to wait...
+WAIT_RESULTS:
+ {
+ my @results;
+
+ # The time to sleep is a tradeoff:
+ # - Too long is a waste of time.
+ # - Too short will cause many retries, wastes time.
+ # So the current value (after trial and error) is...
+ main::mysleep(0.013);
+ open(SLICS,$chipregs) or
+ die("Failed reading from chipregs file $chipregs");
+ while(<SLICS>){
+ s/#.*//;
+ next unless /\S/;
+ @results = /^\s*(\d+)\s+[RW][DI]\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]*)/;
+ if(@results != 4) {
+ main::logit "Failed reading from '$chipregs' ($read_slic,$read_reg,$direct)";
+ die;
+ }
+ }
+ close(SLICS);
+ my $reg = hex($results[1]);
+ if($results[0] ne $read_slic || $reg ne $read_reg) {
+ # We read obsolete values, need to wait some more
+ if(--$retries) {
+ main::debug "$read_slic RD $read_reg -- retry ($results[0], $reg)";
+ redo WAIT_RESULTS;
+ } else {
+ main::logit "Failed: $read_slic RD $read_reg returned $results[0], $reg";
+ die;
+ }
}
+ # Good.
+ @reply = (hex($results[2]), hex($results[3]));
+
}
- close(SLICS);
- die("Failed reading from '$chipregs' ($read_slic,$read_reg,$direct)")
- unless @reply;
if ($direct eq 'S') {
return @reply;
} else {
@@ -230,8 +247,8 @@ sub init_indirect_registers() {
* WS 1E 12 00 00
* WS 1E 13 00 00
-* WS 1E 14 F0 7E
-* WS 1E 15 C0 01
+* WS 1E 14 FD 7E
+* WS 1E 15 77 01
* WS 1E 16 00 00
* WS 1E 17 00 20
@@ -246,23 +263,17 @@ sub init_indirect_registers() {
* WS 1E 1F 00 02
* WS 1E 20 C0 07
-* WS 1E 21 00 26
-* WS 1E 22 F4 0F
+* WS 1E 21 6F 37
+* WS 1E 22 80 1B
* WS 1E 23 00 80
-
-#* WS 1E 24 20 03
-#* WS 1E 25 8C 08
-#* WS 1E 26 00 01
-#* WS 1E 27 10 00
* WS 1E 24 00 08
* WS 1E 25 00 08
* WS 1E 26 00 08
* WS 1E 27 00 08
-* WS 1E 28 00 0C
-* WS 1E 29 00 0C
-* WS 1E 2B 00 01
+* WS 1E 28 00 00
+* WS 1E 2B 00 08 # LCRTL = 5.08 mA
* WS 1E 63 DA 00
* WS 1E 64 60 6B
@@ -277,7 +288,8 @@ sub init_indirect_registers() {
sub init_early_direct_regs() {
return write_to_slic_file("#
* WD 08 00 # Audio Path Loopback Control
-* WD 4A 34 # High Battery Voltage
+* WD 6C 01
+* WD 4A 3F # High Battery Voltage
* WD 4B 10 # Low Battery Voltage
* WD 40 00 # Line Feed Control
#")
@@ -310,35 +322,36 @@ 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;
-
+ my @curr_slics = @SlicNums;
+
+ # initialize counters
+ my @slic_counters = map { 0x1F } @curr_slics;
+
# wait until all slics have finished calibration, or for timeout
- while ($calibration_in_progress) {
- $calibration_in_progress = 0; # until proven otherwise
+ while (@curr_slics) {
my $debug_calib_str = "ManualCalib:: ";
- for my $slic(@SlicNums) {
+ my @next_slics;
+
+ for my $slic (@curr_slics) {
+ write_reg($slic,$write_reg,'D',$slic_counters[$slic]);
+ }
+ main::mysleep $ManualCalibrationSleepTime;
+ for my $slic (@curr_slics) {
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;
+ $debug_calib_str .= sprintf " [%d:%d:%X]",
+ $slic, $slic_counters[$slic], $value;
+ next if $value == 0; # This one is calibrated.
+ if ($slic_counters[$slic] > 0) {
$slic_counters[$slic]--;
- write_reg($slic,$write_reg,'D',$slic_counters[$slic]);
+ push(@next_slics, $slic);
+ } else {
+ main::logit("ERROR: SLIC $slic reached 0 during manual calibration");
}
}
+ @curr_slics = @next_slics;
main::debug($debug_calib_str);
- # TODO: unnecessary sleep in the last round:
- main::mysleep $ManualCalibrationSleepTime;
}
+ main::debug("No more slics to calibrate");
}
sub manual_calibrate() {
@@ -352,41 +365,46 @@ sub auto_calibrate($$) {
#log_calib_params();
# start calibration:
- write_to_slic_file(
- sprintf
- "* WD 60 %02X\n".
- "* WD 61 %02X\n".
- "", $calib_96, $calib_97
-
- );
+ for my $slic(@SlicNums) {
+ write_to_slic_file(
+ sprintf
+ "$slic WD 61 %02X\n".
+ "$slic WD 60 %02X\n".
+ "", $calib_97, $calib_96
+
+ );
+ }
+
# 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++;
+ my $sleep_time = 0.001;
+ my $timeout_time = 0.600; # Maximum from the spec
+ my @curr_slics = @SlicNums;
+ my $sleep_cnt = 0;
+CALIB_LOOP:
+ while(1) {
+ main::mysleep($sleep_time);
+ my @next_slics;
+ for my $slic (@curr_slics) {
+ main::debug("checking slic $slic");
+ my $val = read_reg($slic, 60, 'D');
+ push(@next_slics, $slic) if $val != 0;
}
+ @curr_slics = @next_slics;
+ last unless @curr_slics;
+ if ($sleep_cnt * $sleep_time > $timeout_time) {
+ main::logit("Auto Calibration: Exiting on timeout: $timeout_time.");
+ last CALIB_LOOP;
+ }
+ main::debug("auto_calibrate not done yet($sleep_cnt): @curr_slics");
+ $sleep_cnt++;
}
#log_calib_params();
}
sub calibrate_slics() {
main::debug "Calibrating '$0'";
- auto_calibrate(0x47, 0x1E);
+ auto_calibrate(0x40, 0x1E);
main::debug "after auto_calibrate";
manual_calibrate();
main::debug "after manul_calibrate";
@@ -403,11 +421,23 @@ sub read_defaults() {
}
}
+# Try to identify which slics are valid
+sub check_slics() {
+ my @slics;
+ foreach my $slic (0 .. 7) {
+ my $value = read_reg($slic, 0, 'D');
+ push(@slics, $slic) if $value != 0xFF;
+ }
+ main::logit "Found " . scalar(@slics) . " SLICS (@slics)";
+ return @slics;
+}
+
package main;
main::debug "Starting '$0'";
FXS::read_defaults;
+@SlicNums = FXS::check_slics;
main::debug "before init_indirect_registers";
FXS::init_indirect_registers();
main::debug "after init_indirect_registers";
@@ -438,8 +468,6 @@ 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
* WS 1E 58 00 00
@@ -450,8 +478,9 @@ __DATA__
* WS 1E 5D 00 00
* WS 1E 5E 00 00
* WS 1E 5F 00 00
+
* WS 1E 61 00 00
-* WS 1E 58 00 00
+
* WS 1E C1 00 00
* WS 1E C2 00 00
* WS 1E C3 00 00
@@ -471,31 +500,63 @@ __DATA__
* WS 1E D1 00 00
* WS 1E D2 00 00
* WS 1E D3 00 00
+
+# Clear and disable interrupts
+* WD 12 FF
+* WD 13 FF
+* WD 14 FF
+* WD 15 00
+* WD 16 00
+* WD 17 00
+## Mode(8-bit,u-Law,1 PCLK )
+* WD 01 08 # Disable PCM transfers
+
# Setting of SLICs offsets
# New card initialization
+
+* WD 03 00
+* WD 05 00
+
0 WD 02 00
0 WD 04 00
+0 WD 01 28 # Enable PCM transfers
1 WD 02 08
1 WD 04 08
+1 WD 01 28
2 WD 02 10
2 WD 04 10
+2 WD 01 28
3 WD 02 18
3 WD 04 18
+3 WD 01 28
4 WD 02 20
4 WD 04 20
+4 WD 01 28
5 WD 02 28
5 WD 04 28
+5 WD 01 28
6 WD 02 30
6 WD 04 30
+6 WD 01 28
7 WD 02 38
7 WD 04 38
-* WD 03 00
-* WD 05 00
+7 WD 01 28
# Audio path. (also initialize 0A and 0B here if necessary)
* WD 08 00
* WD 09 00
+* WD 0A 08
+* WD 0B 33
+
+#------ Metering tone
+* WD 2C 00 # Timer dL
+* WD 2D 03 # Timer dH
+* WS 1E 17 61 15 # Amplitue Ramp-up
+* WS 1E 18 61 15 # Max Amplitude
+* WS 1E 19 FB 30 # Frequency
+
+# Ring regs are set by driver
# Automatic/Manual Control: defaults but:
# Cancel AOPN - Power Alarm
@@ -514,39 +575,16 @@ __DATA__
# Loop Current Limit
* WD 47 00
-# Ring VBath:
-* WD 4A 3F
-
+# On-Hook Line Voltage (VOC)
+* WD 48 20
-* WD 6C 01
+# Common Mode Voltage (VCM)
+* WD 49 03
* WS 1E 23 00 80
* WS 1E 24 20 03
-* WS 1E 25 8C 08
-* WS 1E 26 00 01
+* WS 1E 25 8C 00
+* WS 1E 26 00 00
* WS 1E 27 10 00
-#------ Metering tone
-* WS 1E 17 61 15 # Amplitue Ramp-up
-* WS 1E 18 61 15 # Max Amplitude
-* WS 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
+* WD 0E 00
diff --git a/drivers/dahdi/xpp/init_card_2_30 b/drivers/dahdi/xpp/init_card_2_30
index 8dd57ed..efc19a9 100755
--- a/drivers/dahdi/xpp/init_card_2_30
+++ b/drivers/dahdi/xpp/init_card_2_30
@@ -389,51 +389,46 @@ close STDERR;
exit 0;
__DATA__
-* WD 21 28
+* WD 21 08 # Disable PCM transfers
* WD 18 99
* WD 06 00
# ----------- DAA PCM start offset ----------
+* WD 23 00
+* WD 25 00
+
0 WD 22 00
-0 WD 23 00
0 WD 24 00
-0 WD 25 00
+0 WD 21 28 # Enable PCM transfers, when offsets are set
1 WD 22 08
-1 WD 23 00
1 WD 24 08
-1 WD 25 00
+1 WD 21 28
2 WD 22 10
-2 WD 23 00
2 WD 24 10
-2 WD 25 00
+2 WD 21 28
3 WD 22 18
-3 WD 23 00
3 WD 24 18
-3 WD 25 00
+3 WD 21 28
4 WD 22 20
-4 WD 23 00
4 WD 24 20
-4 WD 25 00
+4 WD 21 28
5 WD 22 28
-5 WD 23 00
5 WD 24 28
-5 WD 25 00
+5 WD 21 28
6 WD 22 30
-6 WD 23 00
6 WD 24 30
-6 WD 25 00
+6 WD 21 28
7 WD 22 38
-7 WD 23 00
7 WD 24 38
-7 WD 25 00
+7 WD 21 28
# ----------- DAA ONHOOK --------------------
* WD 05 00