OBJNAM BAUD.SBR  ; Created Sep/84 Last modified 2-Feb-85
; Subroutine to change baud rate of user's or specified terminal
; by Irv Bromberg, Medic/OS Consultants
; 78 Wildginger Way, Toronto, Ontario, CANADA  M3H 5X1
RADIX 10
VEDIT=18
VMINOR=3
VMAJOR=3
VSUB=0

IF EQ,1

To set specified baud rate:

MAP1 Rate,F

XCALL BAUD,(Rate)   or   XCALL BAUD,TrmNam,(Rate)

where Rate is a floating numeric expression or a variable passed by
value (in brackets) and where TrmNam is an optional string
containing the name of terminal whose baud rate is to be changed
(default is user's own terminal), this subroutine will signal ^C to
BASIC if requested baud rate not legal or if a specified terminal is
not found.  If Rate = -1 then sends "break".

To return current baud rate:

XCALL BAUD,Rate   or  XCALL BAUD,TrmNam,Rate

(the difference here is that the floating Rate parameter is passed by
reference rather than by value)

ENDC

SEARCH SYS
SEARCH SYSSYM
SEARCH TRM

Header:  PHDR -1,0,PH$REE!PH$REU

JCB     =A0
Rad50   =A1
Source  =A1
IDV     =A2
Buffer  =A2
ArgBas  =A3
List    =A3
Worksp  =A4
TCB     =A5
Stack   =A5
Atemp   =A6

Code    =D0
Rate    =D1
Size    =D2
SavStk  =D3

       CLR     Code                    ; pre-clear for byte move
       MOV     Stack,SavStk            ; save BASIC stack address
       MOV     JOBCUR,JCB              ; default to user's TCB
       MOV     JOBTRM(JCB),TCB
       CMPB    2(ArgBas),#2            ; is 1st parameter string?
       BNE     Self
       MOV     4(ArgBas),Buffer        ; yes get specified trmnam
       MOV     8(ArgBas),Size
       CMP     Size,#6                 ; take maximum of first 6 chars
       BLOS    10$
       MOV     #6,Size
10$:    DECW    Size                    ; pre-decrement for DBF loop
       MOV     Worksp,Atemp
20$:    MOVB    (Buffer)+,(Atemp)+      ; copy name of terminal
       DBF     Size,20$
       CLRB    @Atemp                  ; terminate with NULL
       MOV     Worksp,Buffer           ; reset to start of trmnam
       CALL    FndTrm                  ; and see if it exists
       BNE     Error
       ADD     #10,ArgBas              ; adjust for extra parameter
Self:   MOV     4(ArgBas),Source        ; get address of baud rate parameter
       CMP     Source,SavStk           ; was parameter passed by value?
       BHIS    SetBaud                 ; no, go set specified baud rate
       MOVW    T.BAU(TCB),Code         ; yes, get current baud rate code
       LSLW    Code,#1                 ; multiply x2 to index baud rate table
       LEA     List,Table              ; index baud rate table
       ADD     Code,List               ; offset by current baud rate code
       MOVW    @List,Rate              ; get baud rate value
       FLTOF   Rate,(Worksp)           ; convert to floating
       MOVB    (Worksp)+,(Source)+
       MOVB    (Worksp)+,(Source)+
       MOVB    (Worksp)+,(Source)+
       MOVB    (Worksp)+,(Source)+
       MOVB    (Worksp)+,(Source)+
       MOVB    (Worksp)+,(Source)+
       RTN

SetBaud:MOVB    (Source)+,(Worksp)+     ; Move byte-by-byte to ensure
       MOVB    (Source)+,(Worksp)+     ; parameter begins on even address.
       MOVB    (Source)+,(Worksp)+
       MOVB    (Source)+,(Worksp)+
       MOVB    (Source)+,(Worksp)+
       MOVB    (Source)+,(Worksp)+
       SUB     #6,Worksp               ; restore workspace register
       FFTOL   @Worksp,Rate            ; desired rate now known
       BEQ     Error                   ; 0 is invalid
       CMP     Rate,#-1                ; -1 means transmit BREAK
       BNE     ChkRate
       PUSHW   T.BAU(TCB)              ; save existing baud rate
       MOV     #2,Code                 ; change to slow rate
       BCALL   WaitOIP
       CLR     D1                      ; Break simulated by 5 NULLs at
       MOV     #5,D3                   ; low baud rate.
       TRMBFQ
       POPW    Code                    ; restore original baud rate
       BR      WaitOIP

ChkRate:LEA     List,Table              ; index baud rate table
ChkTbl: CMPW    Rate,(List)+            ; baud rate match?
       BEQ     WaitOIP                 ; yes, go set it
       INCB    Code                    ; increment to next baud code
       TSTW    @List                   ; 0 is end of table
       BNE     ChkTbl
Error:  ORW     #J.CCC,JOBSTS(JCB)      ; illegal baud rate, signal ^C to BASIC
       RTN

WaitOIP:TSTB    T.STS(TCB)              ; wait for OIP to finish
       BMI     WaitOIP
       SLEEP   #500                    ; allow time for last char to empty
       MOV     T.IDV(TCB),IDV
       MOVW    Code,T.BAU(TCB)         ; update baud code in TCB
       SAVE    D0-D7,A0-A6             ; in case IDV changes anything
       CALL    2(IDV)                  ; IDV to change baud rate
       REST    D0-D7,A0-A6
       RTN

; subroutine to locate a specified terminal's TCB
; input:  A2 points to ASCII string with terminal name
; output: A5=TCB of specified terminal
; if NE after call then terminal was not found
; destroys: D6,D7

FndTrm: PUSH                            ; get some workspace
       MOV     SP,Rad50                ; pack terminal name
       PACK
       PACK
       POP     D6                      ; into D6
       MOV     TRMDFC,TCB
NextTrm:MOV     TCB,D7                  ; test if end of terminals defined
       BEQ     TNotFound               ; 0=end of list
       ADD     #8.,TCB
       MOV     -4(TCB),D7
       CMP     D7,D6                   ; is this the terminal specified?
       BEQ     TFound
       MOV     -8.(TCB),TCB
       BR      NextTrm
TNotFound:LCC   #0                      ; signal terminal not found
TFound: RTN

Table:  ; baud rate lookup table
       WORD    50,75,110,134,150,200,300,600,1200,1800,2000,2400
       WORD    3600,4800,7200,9600,19200,38400
       WORD    0                       ; end of table
       END