LAPORT33 ;MLD/ABBOTT/SLC/RAF - AxSYM BIDRECTIONAL INTERFACE ; 6/12/96 0900 [ 01/12/98 11:20 AM ]
;;5.2;LA;**1001**;DEC 10, 1997
;;5.2;AUTOMATED LAB INSTRUMENTS;**11,19**;Sep 27, 1994
;
; This routine LOOSELY follows the LAPORTXX template. However, this
; routine works ONLY for Abbott's AxSYM machine, and should comply
; with ASTM communication protocols. This pgm will run continuously
; as a background job until the system is taken down OR ^LA("STOP",INST)
; global flag is set. /mld
;
N LARETRY,LATOUT,LATEMP,LAFRAME,LAFRAM,LAEND,LACS,LAFRNUM,LADEV
N LAFRNM,LALINK,LACRLF,LACRETX,LANOCTL1,LANOCTL2,LADATA,LANM
N I,J,T,X,Y,INST,DEB,HOME,BASE,OUT,TOUT,PAR,TSK,NODE,OK,DEBUG,CNT
N NUL,SOH,STX,ETX,EOT,ENQ,ACK,NAK,ETB,LF,CR ; *control chars*
;
S LANM=$T(+0),(HOME,T)=+$E(LANM,7,8) Q:+T<1 Q:$D(^LA("LOCK","D"_T))
; init req'd params
D INIT^LAXSYMU I 'OK QUIT ; chk ^LA(INST,"ERR",$H) for err msg
;
PH1 ; PHase1 - idle/establish link (wait for AxSYM to send data)
S LADATA=$$GETCH I DEBUG D DEBG^LAXSYMU(LADATA,"I")
I LADATA=-1 G @($$CHK) ; idle - chk flags
I LADATA'=ENQ G PH1 ; read until ENQ rec'd
; AxSYM ready to send data so init vars, ACK and drop to PH2
S LAFRAME="",LARETRY=0,LATOUT=15,LAFRNM=0,LALINK=1
D SEND^LAXSYMU(ACK)
;
PH2 ; PHase2 - transfer data (build frame)
S LADATA=$$GETCH
I LADATA=-1 D SET G PH1 ; timed out - goto idle
S LAFRAME=LAFRAME_$C(LADATA) ; build frame
I $L(LAFRAME)>247 D NAK^LAXSYMU("SIZE") G:LARETRY<7 PH2 D SET G PH1
I LADATA=LF G PH3 ; LF=complete frame
I LADATA=EOT G PH3 ; no more data
G PH2
;
PH3 ; PHase3 (validate frame)
D:DEBUG DEBG^LAXSYMU(LAFRAME,"I") ; debug
S X=LAFRAME
I $F(X,$C(EOT)) D SET G PH1 ; EOT not allowed in txt
I $A(X)'=STX D SET G PH1 ; 1st char must be STX
; txt must end w/ ETX or ETB
S LAEND=$S($F(X,$C(ETX)):$F(X,$C(ETX)),1:$F(X,$C(ETB)))
I 'LAEND D NAK^LAXSYMU("LAEND") G PH2:LARETRY<7 D SET G PH1
;
S LAFRAM=$E(X,2,LAEND-1) ; get msg txt
; chk frame numbering sequence
S LAFRNUM=+LAFRAM,LAFRNM=$S(LAFRNM<7:LAFRNM+1,1:0)
I LAFRNM'=LAFRNUM D NAK^LAXSYMU("NUMSQNC") G PH2:LARETRY<7 D SET G PH1
I LAFRNUM'=(LAFRNUM#8) D NAK^LAXSYMU("FRNUM") G PH2:LARETRY<7 D SET G PH1
; chk restricted control chars in txt
I LAFRAM'=$TR(LAFRAM,LANOCTL2) D NAK^LAXSYMU("CTL") G PH2:LARETRY<7 D SET G PH1
; sent checksum must = received checksum
S LACS=$E(X,LAEND,LAEND+1) ; get passed cksum
I LACS'=$$CKSUM^LAXSYMU(LAFRAM) D NAK^LAXSYMU("CKSUM") G PH2:LARETRY<7 D SET G PH1
; chk for CR_LF terminating chars - timeout if NULL, NAK for all others
I $P(X,(LACRETX_LACS),2)="" D SET G PH1
I $P(X,(LACRETX_LACS),2)'=LACRLF D NAK^LAXSYMU("LACRLF") G PH2
;
D UPDT^LAXSYMU,SEND^LAXSYMU(ACK) ; frame OK - save & ACK
G PH2 ; get nxt frame
;
GETCH() ; read 1 char at a time. Returns Ascii value of terminating char
S ^LA(INST,"R")=$H
R *LATEMP:LATOUT
S DEBUG=$D(^LA(DEB,0)) ; debug on? (def=off)
Q LATEMP
;
CHK() ; Chk flags - Returns LINE TAG to branch to
S ^LA(INST,"R")=$H,LATOUT=30 ; update run-time flag
I $D(^LA(INST,"HQ")) S NODE="HQ" Q "DWNLD^LAXSYMDL" ; host query
I $D(^LA(INST,"Q")) S NODE="O" Q "DWNLD^LAXSYMDL" ; d/l l/w list
I '$D(^LA("STOP",INST)) Q "PH1" ; continue
Q "OUT" ; STOP = shutdown
;
SET ; Re-init vars
H 5 ; allow LAXSYM to catch up
K LAFRAM,X,LALINK,LAFRNM
S LATOUT=5,LAFRAME=""
Q:$$CHK["HQ"
H 13 ; force timeout & return to idle
Q
;
OUT ; Main Exit - remove flags, close port
K ^LA("STOP",INST),^LA(INST),^LA("LOCK","D"_INST)
D ^%ZISC
Q
;
TRAP ; Error Trap
D ^LABERR S T=TSK
D SET^LAB G PH1
Q
;
DQ ;Entry point to task job
S LANM=$T(+0),HOME=$E(LANM,7,8) Q:HOME=""!(HOME>99)
I $D(^LAB(62.4,HOME,0)),$L($P(^(0),"^",2)) S ZTIO=$P(^(0),"^",2),ZTRTN=LANM,ZTDTH=$H,ZTDESC="START LAB DIRECT CONNECT PORT "_HOME K ^LA("LOCK","D"_HOME) D ^%ZTLOAD
Q
LAPORT33 ;MLD/ABBOTT/SLC/RAF - AxSYM BIDRECTIONAL INTERFACE ; 6/12/96 0900 [ 01/12/98 11:20 AM ]
+1 ;;5.2;LA;**1001**;DEC 10, 1997
+2 ;;5.2;AUTOMATED LAB INSTRUMENTS;**11,19**;Sep 27, 1994
+3 ;
+4 ; This routine LOOSELY follows the LAPORTXX template. However, this
+5 ; routine works ONLY for Abbott's AxSYM machine, and should comply
+6 ; with ASTM communication protocols. This pgm will run continuously
+7 ; as a background job until the system is taken down OR ^LA("STOP",INST)
+8 ; global flag is set. /mld
+9 ;
+10 NEW LARETRY,LATOUT,LATEMP,LAFRAME,LAFRAM,LAEND,LACS,LAFRNUM,LADEV
+11 NEW LAFRNM,LALINK,LACRLF,LACRETX,LANOCTL1,LANOCTL2,LADATA,LANM
+12 NEW I,J,T,X,Y,INST,DEB,HOME,BASE,OUT,TOUT,PAR,TSK,NODE,OK,DEBUG,CNT
+13 ; *control chars*
NEW NUL,SOH,STX,ETX,EOT,ENQ,ACK,NAK,ETB,LF,CR
+14 ;
+15 SET LANM=$TEXT(+0)
SET (HOME,T)=+$EXTRACT(LANM,7,8)
IF +T<1
QUIT
IF $DATA(^LA("LOCK","D"_T))
QUIT
+16 ; init req'd params
+17 ; chk ^LA(INST,"ERR",$H) for err msg
DO INIT^LAXSYMU
IF 'OK
QUIT
+18 ;
PH1 ; PHase1 - idle/establish link (wait for AxSYM to send data)
+1 SET LADATA=$$GETCH
IF DEBUG
DO DEBG^LAXSYMU(LADATA,"I")
+2 ; idle - chk flags
IF LADATA=-1
GOTO @($$CHK)
+3 ; read until ENQ rec'd
IF LADATA'=ENQ
GOTO PH1
+4 ; AxSYM ready to send data so init vars, ACK and drop to PH2
+5 SET LAFRAME=""
SET LARETRY=0
SET LATOUT=15
SET LAFRNM=0
SET LALINK=1
+6 DO SEND^LAXSYMU(ACK)
+7 ;
PH2 ; PHase2 - transfer data (build frame)
+1 SET LADATA=$$GETCH
+2 ; timed out - goto idle
IF LADATA=-1
DO SET
GOTO PH1
+3 ; build frame
SET LAFRAME=LAFRAME_$CHAR(LADATA)
+4 IF $LENGTH(LAFRAME)>247
DO NAK^LAXSYMU("SIZE")
IF LARETRY<7
GOTO PH2
DO SET
GOTO PH1
+5 ; LF=complete frame
IF LADATA=LF
GOTO PH3
+6 ; no more data
IF LADATA=EOT
GOTO PH3
+7 GOTO PH2
+8 ;
PH3 ; PHase3 (validate frame)
+1 ; debug
IF DEBUG
DO DEBG^LAXSYMU(LAFRAME,"I")
+2 SET X=LAFRAME
+3 ; EOT not allowed in txt
IF $FIND(X,$CHAR(EOT))
DO SET
GOTO PH1
+4 ; 1st char must be STX
IF $ASCII(X)'=STX
DO SET
GOTO PH1
+5 ; txt must end w/ ETX or ETB
+6 SET LAEND=$SELECT($FIND(X,$CHAR(ETX)):$FIND(X,$CHAR(ETX)),1:$FIND(X,$CHAR(ETB)))
+7 IF 'LAEND
DO NAK^LAXSYMU("LAEND")
IF LARETRY<7
GOTO PH2
DO SET
GOTO PH1
+8 ;
+9 ; get msg txt
SET LAFRAM=$EXTRACT(X,2,LAEND-1)
+10 ; chk frame numbering sequence
+11 SET LAFRNUM=+LAFRAM
SET LAFRNM=$SELECT(LAFRNM<7:LAFRNM+1,1:0)
+12 IF LAFRNM'=LAFRNUM
DO NAK^LAXSYMU("NUMSQNC")
IF LARETRY<7
GOTO PH2
DO SET
GOTO PH1
+13 IF LAFRNUM'=(LAFRNUM#8)
DO NAK^LAXSYMU("FRNUM")
IF LARETRY<7
GOTO PH2
DO SET
GOTO PH1
+14 ; chk restricted control chars in txt
+15 IF LAFRAM'=$TRANSLATE(LAFRAM,LANOCTL2)
DO NAK^LAXSYMU("CTL")
IF LARETRY<7
GOTO PH2
DO SET
GOTO PH1
+16 ; sent checksum must = received checksum
+17 ; get passed cksum
SET LACS=$EXTRACT(X,LAEND,LAEND+1)
+18 IF LACS'=$$CKSUM^LAXSYMU(LAFRAM)
DO NAK^LAXSYMU("CKSUM")
IF LARETRY<7
GOTO PH2
DO SET
GOTO PH1
+19 ; chk for CR_LF terminating chars - timeout if NULL, NAK for all others
+20 IF $PIECE(X,(LACRETX_LACS),2)=""
DO SET
GOTO PH1
+21 IF $PIECE(X,(LACRETX_LACS),2)'=LACRLF
DO NAK^LAXSYMU("LACRLF")
GOTO PH2
+22 ;
+23 ; frame OK - save & ACK
DO UPDT^LAXSYMU
DO SEND^LAXSYMU(ACK)
+24 ; get nxt frame
GOTO PH2
+25 ;
GETCH() ; read 1 char at a time. Returns Ascii value of terminating char
+1 SET ^LA(INST,"R")=$HOROLOG
+2 READ *LATEMP:LATOUT
+3 ; debug on? (def=off)
SET DEBUG=$DATA(^LA(DEB,0))
+4 QUIT LATEMP
+5 ;
CHK() ; Chk flags - Returns LINE TAG to branch to
+1 ; update run-time flag
SET ^LA(INST,"R")=$HOROLOG
SET LATOUT=30
+2 ; host query
IF $DATA(^LA(INST,"HQ"))
SET NODE="HQ"
QUIT "DWNLD^LAXSYMDL"
+3 ; d/l l/w list
IF $DATA(^LA(INST,"Q"))
SET NODE="O"
QUIT "DWNLD^LAXSYMDL"
+4 ; continue
IF '$DATA(^LA("STOP",INST))
QUIT "PH1"
+5 ; STOP = shutdown
QUIT "OUT"
+6 ;
SET ; Re-init vars
+1 ; allow LAXSYM to catch up
HANG 5
+2 KILL LAFRAM,X,LALINK,LAFRNM
+3 SET LATOUT=5
SET LAFRAME=""
+4 IF $$CHK["HQ"
QUIT
+5 ; force timeout & return to idle
HANG 13
+6 QUIT
+7 ;
OUT ; Main Exit - remove flags, close port
+1 KILL ^LA("STOP",INST),^LA(INST),^LA("LOCK","D"_INST)
+2 DO ^%ZISC
+3 QUIT
+4 ;
TRAP ; Error Trap
+1 DO ^LABERR
SET T=TSK
+2 DO SET^LAB
GOTO PH1
+3 QUIT
+4 ;
DQ ;Entry point to task job
+1 SET LANM=$TEXT(+0)
SET HOME=$EXTRACT(LANM,7,8)
IF HOME=""!(HOME>99)
QUIT
+2 IF $DATA(^LAB(62.4,HOME,0))
IF $LENGTH($PIECE(^(0),"^",2))
SET ZTIO=$PIECE(^(0),"^",2)
SET ZTRTN=LANM
SET ZTDTH=$HOROLOG
SET ZTDESC="START LAB DIRECT CONNECT PORT "_HOME
KILL ^LA("LOCK","D"_HOME)
DO ^%ZTLOAD
+3 QUIT