[comp.sys.handhelds] Set the clock of your HP-48 -- automatically!

pausch@saaf.se (Paul Schlyter) (04/08/91)

About two months ago, I heard about "Mr Atomic Clock" in Stockholm, Sweden.
This is a time service by modem, started by the Swedish Telecomm Corporation.
Being an occaltation observer, I've always been interested in having access
to an accurate time source out in the field. The HP-48SX seemed to be an
ideal solution, but it's somewhat awkward to set its clock "by hand" to,
say, 0.1 second accuracy. But the HP-48 has an RS-232 connector, and "Mr
Atomic Clock" is available by modem. If there only was a program that could
dial "Mr Atomic Clock", read his time and set the HP-48 clock accordingly...

Of course, I knew of no such program, so I started to write my own. A line
of time information from "Mr Atomic Clock" basically looks like:

------------------------------------------------------------------------------
1991-03-01 09:37:40 VIN 250906003310219910301083748316+5000000 R{tt tid fr}n *
------------------------------------------------------------------------------

where time info is sent as ASCII characters, then a short pause is made
right before the final "*", and the "*" itself is the time mark. So all
you have to do is to sync in on the "*", read the time info on the next line,
process it, and then wait for the next "*" and set the HP-48 clock accordingly
right?

Well, it wasn't quite that easy, mainly because the HP-48 don't seem to have
CPU power enough for real-time processing of this time data (at least not
when programming in RPL, as I intended to do. ML programming may be a whole
other story though). A loop that received the characters one by one, and
checked for a "*" simply wouldn't keep up with the arriving data (which
arrived in the modest baud rate of 1200 baud....).  So I had to try something
different.  Fortunately, the HP-48 has interrupt-driven reception on the
RS-232 line (the buffer seem to be able to hold up to 255 characters). Un-
fortunately I kept losing characters when trying to to data processing and
data reception simultaneously, and it was NOT because I exceeded the 255
buffer size limit - often I ended up with 50-60 chars when I expected 80.

My approach to this was:  let the HP-48 do EITHER data reception OR data
processing. Not both at the same time.

After many experiments, I ended up with a program that works as folows:

1: Check of the modem is there by sending "AT" -- you should get "AT"
echoed back.

2: Send the "ATD<number>" dial string to the modem.

3: Wait for "CONNECT".  If you instead receive "BUSY" or something else,
display this message and quit.

4: Wait a second or two to receive and throw away any initial garbage.

5: Receive a LONG string with 0.1 sec timeout. Essentially, this will wait
for the pause before the next "*". Throw away what's been received.

6: Receive the "*".  Read the HP-48 clock immediately afterwards, using TICKS.

7: Receive the end-of-line, then the following time info string.

8: Turn the modem off-line by sending "+++" to the modem.  Flush the
receive buffer by receiving whatever is there, throw it away.

9: Do a simple "syntax check" of the received time info string. If this check
fails, garbage has been received. Display a message about this, then turn the
modem back on line by sending "ATO", and go back to step 4.

10: Analyze the time info string. Put relevant information in the TPRV object
but first the old TPRV is stored in TPRV2. Check the time difference of the
HP-48 clock and the Atomic Clock. Also check if a transition has been made
between standard and summer (daylight saving) time - such a transition does
NOT mean that the HP_48 clock has gained or lost an hour!

11: Display an info screen on the HP-48, and update the statistics object
TSTAT. The "weight" of this clock set event is proportional to the time
that has passed since you last set the HP-48.

12: Hang up the modem by sending "ATH" to the modem.

13: Done!  FREEZE lets the HP-48 display remain - it can be recalled at
any time by executing INFO.

------------------------------------------------------

Since I wanted to be able to use the HP-48 out in the field to time
astronomical events, I wanted some kind of cable with a button that
could be sensed by the HP-48.  When I made my HP-48 null modem, I
also put a small button on the side of it.  This button simply connects
the XMIT and RECV lines of the RS-232 connector.  When executing the
BUTN object, the HP-48 will repeatedly send a char to its RS-232 port,
then see if the char is available for reception.  If it is available,
the "external button" has been pressed, and the HP-48 clock is read and
the time is left on the stack.  This can be repeated as many times as you
want, until BUTN is terminated by pressing any of the keyboard keys --
a tagged time value is then left on the stack.

This is a very simplistic approach to the problem of reading accurate
times out in the field, but it has several advantages.  Many events may
be timed during a short time interval --they will all be remembered by
the HP-48 (the only thing YOU will have to remember is the order of the
events - if this should be a problem, consider using a tape recorder).
And the "event button" on the null modem at the end of the HP-48 serial
cable enables me to put the HP-48 deep down inside my coat, where it will
be kept warm, even if it's very cold outside.


Below are details of how to interpret the data strings received from
"Mr Atomic Clock", and the listing of my program. I've included two
versions, one with Swedish messages and another with English messages.
Also note that when downloading, you should tell your HP-48 to use a
COMMA, not a point, as a d.p. separator.

Probably there are atomic time services at other places in the world too,
and they may have info strings that look different.  If any one of you
would like to modify my program to work with any of these services, and
wonder about some internal details in my program, please don't hesitate
to ask.  A program like this should be available in many more places in
the world!  The HP-48SX is, when properly set, a quite good portable time
piece, at least when your demands of accuracy doesn't exceed about 0.1 sec.



************* "Mr Atomic Clock" in Stockholm, data format *************

"Mr Atomic Clock".  Phone  +46-8-7410809   (Stockholm, Sweden)

==============================================================================
1991-03-01 09:37:40 VIN 250906003310219910301083748316+5000000 R{tt tid fr}n *
1991-03-01 09:37:41 VIN 250906003310219910301083748316+5000000 Riksm{tplatsen*
1991-03-01 09:37:42 VIN 250906003310219910301083748316+5000000 Tid & frekvens*
1991-03-01 09:37:43 VIN 250906003310219910301083748316+5000000 Telev. Radio  *
1991-03-01 09:37:44 VIN 250906003310219910301083748316+5000000 136 80 Haninge*
1991-03-01 09:37:45 VIN 250906003310219910301083748316+5000000 F|r info ring *
1991-03-01 09:37:46 VIN 250906003310219910301083748316+5000000 08-707 51 97  *
1991-03-01 09:37:47 VIN 250906003310219910301083748316+5000000 Denna metod   *
1991-03-01 09:37:48 VIN 250906003310219910301083748316+5000000 ger +/- 20 ms *
1991-03-01 09:37:49 VIN 250906003310219910301083748316+5000000 Inom Sverige  *
==============================================================================

1991-03-01 09:37:49 VIN 250906003310219910301083748316+5000000 Inom Sverige  *
|    |  |  |  |  |  |   ||| |  | | | |   | | | | |    | |  |   |             ||
A    B  C  D  E  F  G   HIJ K  L M N O   P Q R S T    U V  W   X             YZ


   Col Field Contents
       width

A   1   4+1  Year   \
B   6   2+1  Month  |
C   9   2+1  Date   +---- Mean European Time (MET) = UTC + 1h
D  12   2+1  Hour   |
E  15   2+1  Minute |
F  18   2+1  Second /
G  21   3+1  Som/VIN    Summer (daylight savings) or winter (standard) time
H  25    1   Difference local time - UTC in half hours (2=standard, 4=summer)
I  26    1   Day of week: 1=Mo, 2=Tu, ..., 7=Su
J  27    2   Week number (a Swedish speciality - is it used anywhere else?)
K  29    3   Day number, counted from the start of the year
L  32    2   Month  \
M  34    2   Date   +---- Next change standard/summer time
N  36    2   Hour   /
O  38    4   Year   \
P  42    2   Month  |
Q  44    2   Date   +---- UTC
R  46    2   Hour   |
S  48    2   Minute /
T  50    5   MJD   (JD - 2400000.5)  at 00:00 UTC
U  55    2   DUT1: UTC - UT2 i tenths of a second
V  57    3   Alert about leap second (eg +12 = positive leap sec next dec)
W  60   3+1  Propagation delay corr (not implemented yet in Sweden)
X  64   14   Message (max 10 lines, starts at each 10th line)
Y  78    1   Visible time mark: usually "*", can be changed to "#"
	     if propagation delay correction is implemented
Z  79   (2)  ASCII CR+LF


************** The Atomic Clock Program, getting started **************

Starting up the Atomic Clock program and your HP-48:

1: Connect your HP-48 to a Hayes modem with your HP-48 serial connection
cable and a Null modem connector (only GND, RCV and XMT need to be connected).

2: Modify the contents of TELNO so that it reflects the number YOU must dial,
including area codes etc.

3: Execute the SET object.

4: When the HP-48SX has been successfully set, modify the contents of TSTAT
so that it contains:   [ 0 0 0 ]     Now the statistics will start fresh
with YOUR HP-48.

5: Wait a day or two, execute SET again, to get some data of how much
your HP-48 gains or loses time.

6: Execute TKOR to get your HP-48's time, and the time corrected for how
much your HP-48 gains/loses time.

7: At any time, execute INFO to review some time data of when your HP-48
was last set.

8: To time multpile events, execute BUTN.  Each time you connect the XMT
and RCV lines of your HP-48's RS-232 connector (the two middle connectors),
the corresponding time will be stored on the HP-48 stack.  Pressing any
key on the HP-48 keyboard will terminate this program.  Note that since this
program uses the RS-232 port, it may drain the batteries if run for extended
time periods.


************** The Atomic Clock Program, object overview **************

Objects that are to be used directly

  BUTN     The "Button time" program.  Stop by pressing any key.
  SET      Set the HP-48 clock by modem and atomic clock
  TKORR    Display HP-48 time and corrected time
  INFO     Re-display info screen from when the HP48 was last set
  TELNO    Contains the phone number, in string or numebr form

Data and utility objects

  ATD      Send a "dial" (ATD<number>) string to modem
  ATH      Send a "hangup" (ATH) string to modem
  ATPPP    Send an "off-line" (+++) string to modem
  AT       Send an AT command to modem.
  CST      Define the custom menu
  TSTAT    Statistics: sum of x**2, x(s/day), and dt(days)
  TPRV     Data from when the HP48 was last set
  TPRV2    Data from when the HP48 was set the time before
  TIMSTR   Convert time to time string, nearest second
  TIM2STR  Convert time to time string, nearest 0.01 second
  DATSTR   Convert date to date string
  LREV     Reverse a list
  T2CLK    Convert clock ticks to date and time
  CHKSUMT  Adjust for transition summer/standard time
  TEXTR    Extract fields from TPRV list
  TPSAVE   Update TPRV and TPRV2
  TDIF     Compute time difference in days between two "time" structures
  SCLK     Receive time info string, check it, set the HP48 clock
  ACLK     Set (adjust) the HP48 clock
  TOTIME   Convert string to time value
  TODATE   Convert string to date value
  MCHK     Check for presence of Hayes modem
  MESG     Convert Hayes response to message
  WCONN    Wait for modem "connect"
  ROUND    Round number to n decimals, convert to string


************** The Atomic Clock Program, Swedish version **************

%%HP: T(3)A(D)F(,);
DIR
  BUTN
    \<< MEM DROP 0 \-> stop
      \<<
        DO MEM DROP ,1 STIME
          DO "*" XMIT DROP
          UNTIL 1 SRECV SWAP DROP
            IF KEY DUP
            THEN SWAP DROP 1 'stop' STO
            END OR
          END TIME 6 RND
          IF stop
          THEN "Avslutad" \->TAG
          END
          DO "*" XMIT DROP
          UNTIL 1 SRECV NOT SWAP DROP
          END MEM DROP
        UNTIL stop
        END
      \>> CLOSEIO
    \>>
  SET
    \<< RCLF \-> flags
      \<< -51 SF -41 SF -42 SF CLLCD 1200 BAUD 0 PARITY "Ringer Herr Atomur"
      1 DISP MEM DROP
        IF MCHK
        THEN TELNO ATD
          IF 20 WCONN SWAP 2 DISP
          THEN
            WHILE SCLK
            REPEAT "Fel, f\246rs\246ker igen" 3 DISP "O" AT
            END TPSAVE ACLK "Klockan satt" 3 DISP INFO
          END "H" AT
        ELSE 2 DISP 2 WAIT
        END 9600 BAUD CLOSEIO flags STOF
      \>>
    \>>
  TKORR
    \<< TIME DATE OVER CLLCD DUP TIM2STR "HP48-tid  " SWAP + 1 DISP 2 \->LIST
    TPRV SWAP TDIF 24 / SWAP OVER TSTAT OBJ\-> DROP DROP SWAP / 3600 / *
    \->HMS HMS- TIM2STR "R\228tt tid  " SWAP + 2 DISP TSTAT OBJ\-> DROP SWAP
    SQ 3 PICK / - SWAP 1 - / \v/ * 2 ROUND "Stdavvik  " SWAP + " s" + 3 DISP
    7 FREEZE
    \>>
  INFO
    \<< TPRV LREV OBJ\-> DROP DATSTR "  " + SWAP TIMSTR + 1 DISP "Gick " OVER
    ABS 2 ROUND + SWAP
      IF 0 \>=
      THEN " s f\246re"
      ELSE " s efter"
      END + 2 DISP
      IF DUP 0 \>=
      THEN "Fortar sig "
      ELSE "Saktar sig "
      END SWAP ABS 3 ROUND + " s/d" + 3 DISP
      IF "VIN" ==
      THEN "Somtid b\246rj "
      ELSE "Somtid slut "
      END SWAP + 5 DISP "Vecka " SWAP + "  Dag " + SWAP + 4 DISP "MJD " SWAP
      + "  UT1-C " + SWAP + 6 DISP "N\228sta skottsek " SWAP
      IF DUP "000" ==
      THEN DROP "ej best"
      END + 7 DISP 7 FREEZE
    \>>
  TELNO "7410809"
  ATD
    \<< "DT" SWAP + AT
    \>>
  ATH
    \<< "+++" XMIT DROP 1,2 WAIT "H" AT ,5 WAIT CLOSEIO
    \>>
  ATPPP
    \<< "+++" XMIT DROP
    \>>
  AT
    \<< "AT" SWAP + 13 CHR + XMIT DROP ,1 STIME 100 SRECV DROP DROP
    \>>
  CST { BUTN SET TKORR INFO }
  TSTAT [ 0 0 0 ]
  TPRV { 8,041991 14,5521 -1,03991699988 -,397666764581 "SOM" "09-29 0300"
  "15" "098" "48354" "+0,4" "000" }
  TPRV2 { 6,041991 ,0941 -,675903318995 -,406796279926 "SOM" "09-29 0300"
  "14" "096" "48351" "+0,4" "000" }
  TIMSTR
    \<< 100 / 6 ROUND DUP 3 4 SUB ":" + OVER 5 6 SUB + ":" + SWAP 7 8 SUB +
    \>>
  TIM2STR
    \<< 100 / 8 ROUND DUP 3 4 SUB ":" + OVER 5 6 SUB + ":" + OVER 7 8 SUB +
    "," + SWAP 9 10 SUB +
    \>>
  DATSTR
    \<< 100 / 8 ROUND DUP 7 10 SUB "-" + OVER 5 6 SUB + "-" + SWAP 3 4 SUB +
    \>>
  LREV
    \<< OBJ\->
      IF DUP
      THEN { } SWAP 1 SWAP
        START SWAP +
        NEXT
      ELSE DROP { }
      END
    \>>
  T2CLK
    \<< DUP # 707788800d / DUP # 707788800d * SWAP # 727265d - B\->R 9,031991
    SWAP DATE+ ROT ROT - B\->R 29491200 / \->HMS 2 \->LIST
    \>>
  CHKSUMT
    \<<
      IF TPRV 5 GET TPRV2 5 GET \=/
      THEN
        IF TPRV 5 GET "VIN" ==
        THEN -3600
        ELSE 3600
        END +
      END
    \>>
  TEXTR
    \<< 1 2 SUB OBJ\-> DROP
    \>>
  TPSAVE
    \<< TPRV 'TPRV2' STO DUP TODATE OVER TOTIME 0 0 4 \->LIST OVER 21 23 SUB
    + OVER 32 37 SUB DUP 1 2 SUB "-" + OVER 3 4 SUB + " " + SWAP 5 6 SUB +
    "00" + + OVER 27 28 SUB + OVER 29 31 SUB + OVER 50 54 SUB + OVER DUP 55
    55 SUB "0," + SWAP 56 56 SUB + + OVER 57 59 SUB + 'TPRV' STO
    \>>
  TDIF
    \<< SWAP TEXTR ROT TEXTR ROT HMS- HMS\-> ROT ROT DDAYS 24 * +
    \>>
  SCLK
    \<< ,2 WAIT ,2 STIME 300 SRECV 1 STIME 1 SRECV 4 DROPN ,1 STIME 300 SRECV
    1 STIME 1 SRECV TICKS ,1 STIME 200 SRECV DROP ,5 WAIT ATPPP 1 64 SUB ROT
    DROP SWAP # 1000d + T2CLK ROT ROT + ROT DROP ROT DROP DUP 4 65 SUB SWAP 1
    3 SUB
      IF "*" 13 CHR + 10 CHR + ==
      THEN
        IF DUP SIZE 62 ==
        THEN
          IFERR DUP 25 54 SUB OBJ\-> DROP DUP 55 62 SUB OBJ\-> DROP
          THEN CLEAR 1
          ELSE 0
          END
        ELSE CLEAR 1
        END
      ELSE CLEAR 1
      END
    \>>
  ACLK
    \<< SWAP TPRV SWAP TDIF 3600 * DUP 8192 * NEG CLKADJ CHKSUMT DUP TPRV2
    TPRV TDIF 24 / DUP2 / 1 SWAP DUP SQ 3 \->ARRY OVER * TSTAT + 'TSTAT' STO
    / TPRV 4 ROT PUT 3 ROT PUT 'TPRV' STO DROP
    \>>
  TOTIME
    \<< DUP 12 13 SUB "," + OVER 15 16 SUB + SWAP 18 19 SUB + OBJ\->
    \>>
  TODATE
    \<< DUP 9 10 SUB "," + OVER 6 7 SUB + SWAP 1 4 SUB + OBJ\->
    \>>
  MCHK
    \<< ,3 STIME "AT" 13 CHR + XMIT DROP 15 SRECV DROP 1 2 SUB "AT" ==
      IF DUP
      THEN
      ELSE "Inget Hayes-modem" SWAP
      END
    \>>
  MESG
    \<< DUP 3 6 SUB \-> m
      \<<
        CASE m "CONN" ==
          THEN "Connect"
          END m "BUSY" ==
          THEN "Busy"
          END m "NO C" ==
          THEN "No carrier"
          END m "NO D" ==
          THEN "No dialtone"
          END m "NO A" ==
          THEN "No answer"
          END "No modem"
        END
      \>> SWAP
    \>>
  WCONN
    \<< STIME 6 SRECV DROP MESG 13 CHR 10 CHR + "CONN" + ==
      IF DUP
      THEN 1 STIME 10 SRECV SWAP DROP AND
      ELSE CLOSEIO
      END
    \>>
  ROUND
    \<< RCLF ROT ROT
      IF DUP 0 >
      THEN FIX \->STR
        IF DUP "E" POS
        THEN DROP 0 \->STR
        END
      ELSE DROP STD IP \->STR
      END SWAP STOF
    \>>
END


************** The Atomic Clock Program, English version **************

%%HP: T(3)A(D)F(,);
DIR
  BUTN
    \<< MEM DROP 0 \-> stop
      \<<
        DO MEM DROP ,1 STIME
          DO "*" XMIT DROP
          UNTIL 1 SRECV SWAP DROP
            IF KEY DUP
            THEN SWAP DROP 1 'stop' STO
            END OR
          END TIME 6 RND
          IF stop
	  THEN "Finished" \->TAG
          END
          DO "*" XMIT DROP
          UNTIL 1 SRECV NOT SWAP DROP
          END MEM DROP
        UNTIL stop
        END
      \>> CLOSEIO
    \>>
  SET
    \<< RCLF \-> flags
      \<< -51 SF -41 SF -42 SF CLLCD 1200 BAUD 0 PARITY
      "Calling Mr Atom Clock" 1 DISP MEM DROP
        IF MCHK
        THEN TELNO ATD
          IF 20 WCONN SWAP 2 DISP
          THEN
            WHILE SCLK
	    REPEAT "Error, retrying" 3 DISP "O" AT
	    END TPSAVE ACLK "Clock set" 3 DISP INFO
          END "H" AT
        ELSE 2 DISP 2 WAIT
        END 9600 BAUD CLOSEIO flags STOF
      \>>
    \>>
  TKORR
    \<< TIME DATE OVER CLLCD DUP TIM2STR "HP48 time " SWAP + 1 DISP 2 \->LIST
    TPRV SWAP TDIF 24 / SWAP OVER TSTAT OBJ\-> DROP DROP SWAP / 3600 / *
    \->HMS HMS- TIM2STR "Corr time " SWAP + 2 DISP TSTAT OBJ\-> DROP SWAP
    SQ 3 PICK / - SWAP 1 - / \v/ * 2 ROUND "Std dev   " SWAP + " s" + 3 DISP
    7 FREEZE
    \>>
  INFO
    \<< TPRV LREV OBJ\-> DROP DATSTR "  " + SWAP TIMSTR + 1 DISP "Was " OVER
    ABS 2 ROUND + SWAP
      IF 0 \>=
      THEN " s fast"
      ELSE " s slow"
      END + 2 DISP
      IF DUP 0 \>=
      THEN "Gaining "
      ELSE "Losing  "
      END SWAP ABS 3 ROUND + " s/day" + 3 DISP
      IF "VIN" ==
      THEN "DSTime strt "
      ELSE "DSTime end  "
      END SWAP + 5 DISP "Week " SWAP + "  Day " + SWAP + 4 DISP "MJD " SWAP
      + "  UT1-C " + SWAP + 6 DISP "Next leap sec " SWAP
      IF DUP "000" ==
      THEN DROP "not dec"
      END + 7 DISP 7 FREEZE
    \>>
  TELNO "7410809"
  ATD
    \<< "DT" SWAP + AT
    \>>
  ATH
    \<< "+++" XMIT DROP 1,2 WAIT "H" AT ,5 WAIT CLOSEIO
    \>>
  ATPPP
    \<< "+++" XMIT DROP
    \>>
  AT
    \<< "AT" SWAP + 13 CHR + XMIT DROP ,1 STIME 100 SRECV DROP DROP
    \>>
  CST { BUTN SET TKORR INFO }
  TSTAT [ 0 0 0 ]
  TPRV { 8,041991 14,5521 -1,03991699988 -,397666764581 "SOM" "09-29 0300"
  "15" "098" "48354" "+0,4" "000" }
  TPRV2 { 6,041991 ,0941 -,675903318995 -,406796279926 "SOM" "09-29 0300"
  "14" "096" "48351" "+0,4" "000" }
  TIMSTR
    \<< 100 / 6 ROUND DUP 3 4 SUB ":" + OVER 5 6 SUB + ":" + SWAP 7 8 SUB +
    \>>
  TIM2STR
    \<< 100 / 8 ROUND DUP 3 4 SUB ":" + OVER 5 6 SUB + ":" + OVER 7 8 SUB +
    "," + SWAP 9 10 SUB +
    \>>
  DATSTR
    \<< 100 / 8 ROUND DUP 7 10 SUB "-" + OVER 5 6 SUB + "-" + SWAP 3 4 SUB +
    \>>
  LREV
    \<< OBJ\->
      IF DUP
      THEN { } SWAP 1 SWAP
        START SWAP +
        NEXT
      ELSE DROP { }
      END
    \>>
  T2CLK
    \<< DUP # 707788800d / DUP # 707788800d * SWAP # 727265d - B\->R 9,031991
    SWAP DATE+ ROT ROT - B\->R 29491200 / \->HMS 2 \->LIST
    \>>
  CHKSUMT
    \<<
      IF TPRV 5 GET TPRV2 5 GET \=/
      THEN
        IF TPRV 5 GET "VIN" ==
        THEN -3600
        ELSE 3600
        END +
      END
    \>>
  TEXTR
    \<< 1 2 SUB OBJ\-> DROP
    \>>
  TPSAVE
    \<< TPRV 'TPRV2' STO DUP TODATE OVER TOTIME 0 0 4 \->LIST OVER 21 23 SUB
    + OVER 32 37 SUB DUP 1 2 SUB "-" + OVER 3 4 SUB + " " + SWAP 5 6 SUB +
    "00" + + OVER 27 28 SUB + OVER 29 31 SUB + OVER 50 54 SUB + OVER DUP 55
    55 SUB "0," + SWAP 56 56 SUB + + OVER 57 59 SUB + 'TPRV' STO
    \>>
  TDIF
    \<< SWAP TEXTR ROT TEXTR ROT HMS- HMS\-> ROT ROT DDAYS 24 * +
    \>>
  SCLK
    \<< ,2 WAIT ,2 STIME 300 SRECV 1 STIME 1 SRECV 4 DROPN ,1 STIME 300 SRECV
    1 STIME 1 SRECV TICKS ,1 STIME 200 SRECV DROP ,5 WAIT ATPPP 1 64 SUB ROT
    DROP SWAP # 1000d + T2CLK ROT ROT + ROT DROP ROT DROP DUP 4 65 SUB SWAP 1
    3 SUB
      IF "*" 13 CHR + 10 CHR + ==
      THEN
        IF DUP SIZE 62 ==
        THEN
          IFERR DUP 25 54 SUB OBJ\-> DROP DUP 55 62 SUB OBJ\-> DROP
          THEN CLEAR 1
          ELSE 0
          END
        ELSE CLEAR 1
        END
      ELSE CLEAR 1
      END
    \>>
  ACLK
    \<< SWAP TPRV SWAP TDIF 3600 * DUP 8192 * NEG CLKADJ CHKSUMT DUP TPRV2
    TPRV TDIF 24 / DUP2 / 1 SWAP DUP SQ 3 \->ARRY OVER * TSTAT + 'TSTAT' STO
    / TPRV 4 ROT PUT 3 ROT PUT 'TPRV' STO DROP
    \>>
  TOTIME
    \<< DUP 12 13 SUB "," + OVER 15 16 SUB + SWAP 18 19 SUB + OBJ\->
    \>>
  TODATE
    \<< DUP 9 10 SUB "," + OVER 6 7 SUB + SWAP 1 4 SUB + OBJ\->
    \>>
  MCHK
    \<< ,3 STIME "AT" 13 CHR + XMIT DROP 15 SRECV DROP 1 2 SUB "AT" ==
      IF DUP
      THEN
      ELSE "No Hayes modem" SWAP
      END
    \>>
  MESG
    \<< DUP 3 6 SUB \-> m
      \<<
        CASE m "CONN" ==
          THEN "Connect"
          END m "BUSY" ==
          THEN "Busy"
          END m "NO C" ==
          THEN "No carrier"
          END m "NO D" ==
          THEN "No dialtone"
          END m "NO A" ==
          THEN "No answer"
          END "No modem"
        END
      \>> SWAP
    \>>
  WCONN
    \<< STIME 6 SRECV DROP MESG 13 CHR 10 CHR + "CONN" + ==
      IF DUP
      THEN 1 STIME 10 SRECV SWAP DROP AND
      ELSE CLOSEIO
      END
    \>>
  ROUND
    \<< RCLF ROT ROT
      IF DUP 0 >
      THEN FIX \->STR
        IF DUP "E" POS
        THEN DROP 0 \->STR
        END
      ELSE DROP STD IP \->STR
      END SWAP STOF
    \>>
END

********************** That's it! Happy clocking! ************************


Paul Schlyter
Usenet:  pausch@saaf.se
FidoNet: 2:201/600.2

-- 
---
Paul Schlyter (pausch@saaf.se)
Svensk Amat|rAstronomisk F|rening
Stockholm, Sweden