48
48
my $program = basename("$0");
49
49
my $init_dir = dirname("$0");
50
BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir", "$init_dir/zconf"); }
50
BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); }
51
51
use XppConfig $init_dir;
70
70
# Arrange for error logging
72
72
$unit_id = 'Interactive';
73
main::debug "Interactive startup";
73
debug "Interactive startup";
75
75
$unit_id = "$ENV{XBUS_NAME}/UNIT-$ENV{UNIT_NUMBER}";
76
76
open (STDERR, "| logger -t $program -p kern.info") || die;
77
main::debug "Non Interactive startup";
77
debug "Non Interactive startup";
149
149
write_to_slic_file(
150
150
sprintf("%s R%s %02X", $read_slic, $direct, $read_reg));
151
main::mysleep(0.005);
152
open(SLICS,$chipregs) or
153
die("Failed reading from chipregs file $chipregs");
154
#awk '/^SLIC_REPLY:/{print $5}' $SLICS | cut -dx -f2
158
# main::debug "answer line: $_";
162
if (/^ \d*\s+[RW][DI]\s+[[:xdigit:]]+\s+([[:xdigit:]]+)\s+([[:xdigit:]]*)/){
163
@reply = (hex($1), hex($2));
164
#main::debug "got [$reply]";
167
main::logit("Got from '$chipregs' a non-matching line '$_'");
153
# If the command queue is long, we may need to wait...
158
# The time to sleep is a tradeoff:
159
# - Too long is a waste of time.
160
# - Too short will cause many retries, wastes time.
161
# So the current value (after trial and error) is...
162
main::mysleep(0.013);
163
open(SLICS,$chipregs) or
164
die("Failed reading from chipregs file $chipregs");
168
@results = /^\s*(\d+)\s+[RW][DI]\s+([[:xdigit:]]+)\s+([[:xdigit:]]+)\s+([[:xdigit:]]*)/;
170
main::logit "Failed reading from '$chipregs' ($read_slic,$read_reg,$direct)";
175
my $reg = hex($results[1]);
176
if($results[0] ne $read_slic || $reg ne $read_reg) {
177
# We read obsolete values, need to wait some more
179
main::debug "$read_slic RD $read_reg -- retry ($results[0], $reg)";
182
main::logit "Failed: $read_slic RD $read_reg returned $results[0], $reg";
187
@reply = (hex($results[2]), hex($results[3]));
171
die("Failed reading from '$chipregs' ($read_slic,$read_reg,$direct)")
173
190
if ($direct eq 'S') {
277
288
sub init_early_direct_regs() {
278
289
return write_to_slic_file("#
279
290
* WD 08 00 # Audio Path Loopback Control
280
* WD 4A 34 # High Battery Voltage
292
* WD 4A 3F # High Battery Voltage
281
293
* WD 4B 10 # Low Battery Voltage
282
294
* WD 40 00 # Line Feed Control
310
322
sub manual_calibrate_loop($$) {
311
323
my $write_reg = shift;
312
324
my $read_reg = shift;
314
# counters to count down to (at most) 0
315
my @slic_counters = ();
316
for my $i (0 .. $#SlicNums) {
317
$slic_counters[$i] = 0x1F;
321
my $calibration_in_progress = 1;
322
write_reg('*', $write_reg, 'D', 0x1F);
323
main::mysleep $ManualCalibrationSleepTime;
325
my @curr_slics = @SlicNums;
327
# initialize counters
328
my @slic_counters = map { 0x1F } @curr_slics;
325
330
# wait until all slics have finished calibration, or for timeout
326
while ($calibration_in_progress) {
327
$calibration_in_progress = 0; # until proven otherwise
331
while (@curr_slics) {
328
332
my $debug_calib_str = "ManualCalib:: ";
329
for my $slic(@SlicNums) {
335
for my $slic (@curr_slics) {
336
write_reg($slic,$write_reg,'D',$slic_counters[$slic]);
338
main::mysleep $ManualCalibrationSleepTime;
339
for my $slic (@curr_slics) {
330
340
my $value = read_reg($slic, $read_reg, 'D');
331
$debug_calib_str .= " [$slic_counters[$slic]:$value]";
332
if ($value != 0 && $slic_counters[$slic] > 0) {
333
$calibration_in_progress = 1;
341
$debug_calib_str .= sprintf " [%d:%d:%X]",
342
$slic, $slic_counters[$slic], $value;
343
next if $value == 0; # This one is calibrated.
344
if ($slic_counters[$slic] > 0) {
334
345
$slic_counters[$slic]--;
335
write_reg($slic,$write_reg,'D',$slic_counters[$slic]);
346
push(@next_slics, $slic);
348
main::logit("ERROR: SLIC $slic reached 0 during manual calibration");
351
@curr_slics = @next_slics;
338
352
main::debug($debug_calib_str);
339
# TODO: unnecessary sleep in the last round:
340
main::mysleep $ManualCalibrationSleepTime;
354
main::debug("No more slics to calibrate");
344
357
sub manual_calibrate() {
353
366
#log_calib_params();
354
367
# start calibration:
359
"", $calib_96, $calib_97
368
for my $slic(@SlicNums) {
371
"$slic WD 61 %02X\n".
372
"$slic WD 60 %02X\n".
373
"", $calib_97, $calib_96
362
378
# wait until all slics have finished calibration, or for timeout
379
# time periods in seconds:
380
my $sleep_time = 0.001;
381
my $timeout_time = 0.600; # Maximum from the spec
382
my @curr_slics = @SlicNums;
363
383
my $sleep_cnt = 0;
364
# time periods in seconds:
365
my $sleep_time = 0.1;
366
my $timeout_time = 2;
367
CALIB_LOOP: for my $slic (@SlicNums) {
368
main::debug("checking slic $slic");
370
if ((read_reg($slic, 60, 'D')) == 0) {
371
# move to next register
372
main::debug("slic $slic calibrated");
375
if ( $sleep_cnt > $timeout_time/$sleep_time) {
376
main::debug("Auto Calibration: Exiting on timeout: $timeout_time.");
379
main::debug("auto_calibrate not done yet: slic #$slic");
386
main::mysleep($sleep_time);
388
for my $slic (@curr_slics) {
389
main::debug("checking slic $slic");
390
my $val = read_reg($slic, 96, 'D');
391
push(@next_slics, $slic) if $val != 0;
393
@curr_slics = @next_slics;
394
last unless @curr_slics;
395
if ($sleep_cnt * $sleep_time > $timeout_time) {
396
main::logit("Auto Calibration: Exiting on timeout: $timeout_time.");
399
main::debug("auto_calibrate not done yet($sleep_cnt): @curr_slics");
384
402
#log_calib_params();
387
405
sub calibrate_slics() {
388
main::logit "Calibrating '$0'";
389
auto_calibrate(0x47, 0x1E);
406
main::debug "Calibrating '$0'";
407
auto_calibrate(0x40, 0x1E);
390
408
main::debug "after auto_calibrate";
391
409
manual_calibrate();
392
410
main::debug "after manul_calibrate";
393
411
auto_calibrate(0x40, 0x01);
394
412
main::debug "after auto_calibrate 2";
395
main::logit "Continue '$0'";
413
main::debug "Continue '$0'";
398
416
sub read_defaults() {
424
# Try to identify which slics are valid
427
foreach my $slic (0 .. 7) {
428
my $value = read_reg($slic, 0, 'D');
429
push(@slics, $slic) if $value != 0xFF;
431
main::logit "Found " . scalar(@slics) . " SLICS (@slics)";
408
main::logit "Starting '$0'";
437
main::debug "Starting '$0'";
410
439
FXS::read_defaults;
440
@SlicNums = FXS::check_slics;
411
441
main::debug "before init_indirect_registers";
412
442
FXS::init_indirect_registers();
413
443
main::debug "after init_indirect_registers";
434
main::logit "Ending '$0'";
464
main::debug "Ending '$0'";
438
468
# ----------------------------------==== 8-channel FXS unit initialization ===-----------------------------------------
441
# Change SLICs states to "Open state"s (Off,all transfers tristated to avoid data collision), Voltage sense
444
472
# Flush out energy accumulators
504
# Clear and disable interrupts
512
## Mode(8-bit,u-Law,1 PCLK )
513
* WD 01 08 # Disable PCM transfers
475
515
# Setting of SLICs offsets
476
516
# New card initialization
523
0 WD 01 28 # Enable PCM transfers
496
546
# Audio path. (also initialize 0A and 0B here if necessary)
552
#------ Metering tone
553
* WD 2C 00 # Timer dL
554
* WD 2D 03 # Timer dH
555
* WS 1E 17 61 15 # Amplitue Ramp-up
556
* WS 1E 18 61 15 # Max Amplitude
557
* WS 1E 19 FB 30 # Frequency
559
# Ring regs are set by driver
500
561
# Automatic/Manual Control: defaults but:
501
562
# Cancel AOPN - Power Alarm
514
575
# Loop Current Limit
578
# On-Hook Line Voltage (VOC)
581
# Common Mode Voltage (VCM)
529
#------ Metering tone
530
* WS 1E 17 61 15 # Amplitue Ramp-up
531
* WS 1E 18 61 15 # Max Amplitude
532
* WS 1E 19 FB 30 # Frequency
533
* WD 2C 00 # Timer dL
534
* WD 2D 03 # Timer dH
536
# ------------------------------------- Initialization of direct registers --------------------------------------------
538
# Mode(8-bit,u-Law,1 PCLK ) setting, Loopbacks and Interrupts clear
546
# Clear pending interrupts