diff -r c39e37d59638 -r 5e67754f6457 bbabble --- a/bbabble Thu Nov 21 14:01:21 2013 +0000 +++ b/bbabble Fri Jul 03 10:25:08 2020 -0400 @@ -2,12 +2,12 @@ #====================================================================== # B B A B B L E # doc: Thu Mar 11 01:00:51 2004 -# dlm: Wed Dec 1 14:31:14 2010 +# dlm: Fri Jul 3 10:12:51 2020 # (c) 2004 A.M. Thurnherr -# uE-Info: 49 73 NIL 0 0 72 10 2 8 NIL ofnI +# uE-Info: 58 0 NIL 0 0 72 10 2 8 NIL ofnI #====================================================================== -# Broad Band Babble --- talk to 1--2 RDI ADCPs +# Broad Band Babble --- talk to 1--2 RDI ADCPs or other serial instruments # HISTORY: # Mar 5, 2004: - written first, one-page-long proof-of-concept version @@ -47,6 +47,14 @@ # Aug 26, 2010: - added -y)modem receive # Oct 18, 2010: - added -u option to default ymodem receive call # Dec 1, 2010: - BUG: -y with empty-string option argument did not work +# Jun 18, 2018: - explicitly implemented code to disable download on -y "" +# - BUG: one debug message had -s wrong way round +# - added state-change test required when Arduino closes USB connection +# - BUG: non-existing ttys had stupid error messages +# - made -s default and added -a to show async output, which is for debugging only +# - changed default to use -m unless 2 devices are chosen +# - begin implementing non-R)DI mode (currently, upload only) +# Jul 3, 2020: - expunged master/slave terminology #---------------------------------------------------------------------- # USAGE @@ -54,33 +62,25 @@ use Getopt::Std; -$USAGE = "Usage: $0 [-m)onochrome] [-s)uppress async output] " . - "[-y)modem receive ] " . +$USAGE = "Usage: $0 [-m)onochrome] [-s)uppress async output(default)] [produce -a)sync ouput]" . + "[-y)modem receive ] [non-R)DI mode]" . " [tty1_device]\n"; -die($USAGE) unless (getopts("msy:")); +die($USAGE) unless (getopts("amRsy:")); +$opt_s = 1 unless ($opt_a); +$opt_m = 1 unless (@ARGV > 1); + +#============================== USER MANUAL ============================== # bbabble is started with 1 or 2 arguments, which are tty special files. # On LINUX, /dev/ttyS0 is com1: /dev/ttyS1 is com2: /dev/ttyUSB0 is the # first USB tty port, /dev/ttyUSB1 is the 2nd, &c. If two ttys are # specified bbabble can talk to two instruments in parallel. Communication # with The first (second) port is shown in red (blue). For consistency -# with the color scheme used by the LDEO expect scripts, the master -# (downlooker) should be connected to the first tty given on the command -# line. - -# On some (especially BSD-based) systems there are separate tty -# device files for dialin and dialout operations. Only the latter work -# with bbabble. They traditionally have names matching /dev/cu* (e.g. -# /dev/cuad0 for the first serial # port in FreeBSD). - -# In order to have read/write access to the device files, the user -# that is to run bbabble should be added to the group that owns -# the tty device files (e.g. dialer on FreeBSD). - -# The -m option suppresses color ouput and -s suppresses the asynchronous -# messages generated by bbabble and printed in curly braces. Both -# options should be used if bbabble is run within expect(1). +# with the color scheme used by the LDEO expect scripts, the instrument +# sending the sync pulses (downlooker) should be connected to the first +# tty given on the command line. When only one port is specified, the +# -m)onochrome option is assumed. # Upon startup, bbabble prints a help message showing the current # "foreground" instrument as well as a list of legal keyboard commands. @@ -115,6 +115,17 @@ # instrument. The command file may contain any valid RDI command, empty # lines, as well as comments beginning with a semicolon (;). +#====================== USAGE NOTES ============================== + +# On some (especially BSD-based) systems there are separate tty +# device files for dialin and dialout operations. Only the latter work +# with bbabble. They traditionally have names matching /dev/cu* (e.g. +# /dev/cuad0 for the first serial # port in FreeBSD). + +# In order to have read/write access to the device files, the user +# that is to run bbabble should be added to the group that owns +# the tty device files (e.g. dialer on FreeBSD). + # Upon startup, bbabble expects to communicate with the ADCPs at 9600bps # (baud). If the user sends a BREAK (^C) and garbage is produced the # instrument's default baud rate is probably set to a different value. @@ -247,15 +258,17 @@ # If -y is not given, bbabble trys to find one of the standard ymodem # executables. Using -y allows options to be set. -if (length($opt_y) > 0) { - $receive_ymodem = $opt_y; +if (defined($opt_y)) { + if (length($opt_y) > 0) { + $receive_ymodem = $opt_y; + } } else { - chomp($receive_ymodem = `which lrb 2>/dev/null`); - chomp($receive_ymodem = `which rb 2>/dev/null`) - if ($receive_ymodem eq ''); - die("$0: cannot find rb or lrb\n") - if ($receive_ymodem eq ''); - $receive_ymodem .= ' -u'; # keep upper-case filenames + chomp($receive_ymodem = `which lrb 2>/dev/null`); + chomp($receive_ymodem = `which rb 2>/dev/null`) + if ($receive_ymodem eq ''); + die("$0: cannot find rb or lrb\n") + if ($receive_ymodem eq ''); + $receive_ymodem .= ' -u'; # keep upper-case filenames } # When uploading command files, each command is sent after a prompt @@ -330,10 +343,12 @@ } my(@sfd); # TTYs +-c $TTY0 || die("$TTY0: no such file or directory\n"); open(TTY0,'+>',$TTY0) || die("$TTY0: $!\n"); $sfd[0] = fileno(TTY0); if (defined($TTY1)) { select(undef,undef,undef,$naptime); # KEYSPAN 49W requires this + -c $TTY1 || die("$TTY1: no such file or directory\n"); open(TTY1,'+>',$TTY1) || die("$TTY1: $!\n"); $sfd[1] = fileno(TTY1); } @@ -386,7 +401,7 @@ | POSIX::CS8()); $t->setcc(POSIX::VMIN,1); $t->setcc(POSIX::VTIME,0); set_speed($t,$id,$DEFAULT_SPEED[$id]); - if ($opt_s) { + unless ($opt_s) { print($COLOR[$id]) unless ($opt_m); print("{TTY $id READY}"); } @@ -402,7 +417,9 @@ $rcv_state[$id] == $BUFFER); vec($rin,$sfd[$id],1) = 1; } - + last unless ($rcv_state[$id] == $ECHO || # needed when Arduino USB interface is closed at other end + $rcv_state[$id] == $BUFFER); + #------------------------------ # DOWNLOAD DATA FROM INSTRUMENT #------------------------------ @@ -807,7 +824,9 @@ if ($rcv_state[$cid]&$DOWNLOAD){ print(STDERR "$COLOR[$cid]\{DOWNLOAD IN PROGRESS --- ^C TO ABORT}\n"); } else { - $tmp = $rcv_state[$cid]&~$ECHO; $rcv_state[$cid] = $tmp|$BUFFER; + unless ($opt_R) { + $tmp = $rcv_state[$cid]&~$ECHO; $rcv_state[$cid] = $tmp|$BUFFER; + } print($RESET); cookedmode(); do { @@ -815,8 +834,10 @@ if ($_ eq '') { # no file name given print("{upload canceled}\n"); rawmode(); - $tmp = $rcv_state[$cid]&~$BUFFER; $rcv_state[$cid] = $tmp|$FLUSH; - wait_for_bit_cleared($cid,$FLUSH); + unless ($opt_R) { + $tmp = $rcv_state[$cid]&~$BUFFER; $rcv_state[$cid] = $tmp|$FLUSH; + wait_for_bit_cleared($cid,$FLUSH); + } next KEYSTROKE; } unless (open(CF,$_)) { @@ -825,28 +846,33 @@ } } while (0); rawmode(); - $tmp = $rcv_state[$cid]&~$BUFFER; $rcv_state[$cid] = $tmp|$FLUSH; - wait_for_bit_cleared($cid,$FLUSH); - my($cmd) = next_cmd(CF); # read ahead (last cmd may ... - my($next_cmd); # ... not generate prompt) - while (defined($next_cmd = next_cmd(CF))) { - $rcv_state[$cid] = $UPLOAD; - if ($cmd eq '') { - send_BREAK($cid); - } else { - POSIX::write($sfd[$cid],"$cmd\r",length($cmd)+1); + if ($opt_R) { # non-RDI mode: dump entire file contents raw + my($buf,$nread); + while (($nread = read(CF,$buf,1)) > 0) { # nice small chunks + POSIX::write($sfd[$cid],$buf,$nread); + } + } else { # RDI mode: parse command file and send command by command + $tmp = $rcv_state[$cid]&~$BUFFER; $rcv_state[$cid] = $tmp|$FLUSH; + wait_for_bit_cleared($cid,$FLUSH); + my($cmd) = next_cmd(CF); # read ahead (last cmd may ... + my($next_cmd); # ... not generate prompt) + while (defined($next_cmd = next_cmd(CF))) { + $rcv_state[$cid] = $UPLOAD; + if ($cmd eq '') { + send_BREAK($cid); + } else { + POSIX::write($sfd[$cid],"$cmd\r",length($cmd)+1); + } + $cmd = $next_cmd; + wait_for_bit_set($cid,$ECHO); # NOT SURE!!! + $tmp = $rcv_state[$cid]&~$ECHO; $rcv_state[$cid] = $tmp|$BUFFER; + print("\n${RESET}{upload finished}\n"); + $tmp = $rcv_state[$cid]&~$BUFFER; $rcv_state[$cid] = $tmp|$FLUSH; + wait_for_bit_cleared($cid,$FLUSH); } - $cmd = $next_cmd; - wait_for_bit_set($cid,$ECHO); # NOT SURE!!! } close(CF); - POSIX::write($sfd[$cid],"$cmd\r",length($cmd)+1); # last cmd - - $tmp = $rcv_state[$cid]&~$ECHO; $rcv_state[$cid] = $tmp|$BUFFER; - print("\n${RESET}{upload finished}\n"); - $tmp = $rcv_state[$cid]&~$BUFFER; $rcv_state[$cid] = $tmp|$FLUSH; - wait_for_bit_cleared($cid,$FLUSH); } } @@ -855,15 +881,19 @@ #-------------------------- elsif ($char == 24) { - if ($rcv_state[$cid]&$DOWNLOAD){ - print(STDERR "$COLOR[$cid]\{DOWNLOAD IN PROGRESS --- ^C TO ABORT}\n"); + if (defined($receive_ymodem)) { + if ($rcv_state[$cid]&$DOWNLOAD){ + print(STDERR "$COLOR[$cid]\{DOWNLOAD IN PROGRESS --- ^C TO ABORT}\n"); + } else { + $rcv_state[$cid] = $SET_DOWNLOAD_SPEED; + wait_for_bit_set($cid,$ECHO); + $rcv_state[$cid] = $DOWNLOAD; # start waiting for instr. ready + POSIX::write($sfd[$cid],"$START_DOWNLOAD_RDI_COMMAND\r", + length($START_DOWNLOAD_RDI_COMMAND)+1); + wait_for_bit_set($cid,$ECHO); + } } else { - $rcv_state[$cid] = $SET_DOWNLOAD_SPEED; - wait_for_bit_set($cid,$ECHO); - $rcv_state[$cid] = $DOWNLOAD; # start waiting for instr. ready - POSIX::write($sfd[$cid],"$START_DOWNLOAD_RDI_COMMAND\r", - length($START_DOWNLOAD_RDI_COMMAND)+1); - wait_for_bit_set($cid,$ECHO); + print(STDERR "$COLOR[$cid]\{NO YMODEM RECEIVER PROGRAM SPECIFIED}\n"); } }