OSDN Git Service

V309
[fast-forth/master.git] / forthMSP430FR_TERM_HALF.asm
index a28736b..e051b3e 100644 (file)
@@ -1,40 +1,38 @@
 ; -*- coding: utf-8 -*-
-
+;
 ; ---------------------------------------
-; TERMINAL driver for FastForth target
+; UART TERMINAL driver for FastForth target
 ; ---------------------------------------
-;                     +---------------------------+
-; ------              |    +-----------------+    |
-; WIRING              |    |    +--------+   |    |
-; ------              |    |    |        |   |    |
-; FastForth target   TXD  RXD  RTS <--> CTS TXD  RXD  UARTtoUSB <--> COMx <--> TERMINAL
-; -----------------------------------------------------------------------------------------
-; MSP_EXP430FR5739   P2.0 P2.1 P2.2                   PL2303TA                 TERATERM.EXE
-; MSP_EXP430FR5969   P2.0 P2.1 P4.1                   PL2303HXD
-; MSP_EXP430FR5994   P2.0 P2.1 P4.2                   CP2102
-; MSP_EXP430FR6989   P3.4 P3.5 P3.0   
-; MSP_EXP430FR4133   P1.0 P1.1 P2.3   
-; CHIPSTICK_FR2433   P1.4 P1.5 P3.2       
-; MSP_EXP430FR2433   P1.4 P1.5 P1.0       
+;
+;                     +---------------------------------------+
+;                     |    +-----------------------------+    |
+;                     |    |    +------(option)-----+    |    |
+;                     |    |    |                   |    |    |
+; FastForth target:  TXD  RXD  RTS  connected to : CTS  TXD  RXD of UARTtoUSB <--> COMx <--> TERMINAL
+; ----------------   ---  ---  ---                 ---  ---  ---    -------------------------------------
+; MSP_EXP430FR5739   P2.0 P2.1 P2.2                                 PL2303TA                 TERATERM.EXE
+; MSP_EXP430FR5969   P2.0 P2.1 P4.1                                 PL2303HXD
+; MSP_EXP430FR5994   P2.0 P2.1 P4.2                                 CP2102
+; MSP_EXP430FR6989   P3.4 P3.5 P3.0
+; MSP_EXP430FR4133   P1.0 P1.1 P2.3
+; CHIPSTICK_FR2433   P1.4 P1.5 P3.2
+; MSP_EXP430FR2433   P1.4 P1.5 P1.0
 ; MSP_EXP430FR2355   P4.3 P4.2 P2.0
 ; LP_MSP430FR2476    P1.4 P1.5 P6.1
-
-
+;
 ;-------------------------------------------------------------------------------
-; UART TERMINAL: QABORT ABORT_TERM COLD_TERM INI_TERM RXON RXOFF
+; UART TERMINAL: QABORT COLD_TERM INIT_TERM RXON RXOFF
 ;-------------------------------------------------------------------------------
-; define run-time part of ABORT"
-;Z ?ABORT   xi f c-addr u --      abort & print msg.
-;            FORTHWORD "?ABORT"
+
+; define run-time part of ABORT"    ; if f is true display msg. then abort current process
 QABORT      CMP #0,2(PSP)           ; -- f c-addr u         test flag f
-            JNZ ABORT_TERM          ;
+            JNZ ABORT_TERM          ;               see forthMSP430FR_TERM_xxxx.asm below
 THREEDROP   ADD #4,PSP              ; -- u
-            MOV @PSP+,TOS           ; -- 
-            MOV @IP+,PC             ;
+            JMP DROP                ;
 ; ----------------------------------;
-ABORT_TERM                          ; exit from downloading file then reinit some variables via INI_FORTH
+UART_ABORT_TERM                     ; exit from downloading then reinit some variables via INIT_FORTH
 ; ----------------------------------;
-            CALL #RXON              ; PFA resume downloading source file if any
+ABORT_TERM  CALL #RXON              ; resume downloading source file if any
 A_UART_LOOP BIC #RX_TERM,&TERM_IFG  ; clear RX_TERM
             MOV &FREQ_KHZ,Y         ; 1000, 2000, 4000, 8000, 16000, 240000
 A_USB_LOOPJ MOV #65,X               ; 2~        <-------+ linux with minicom seems very very slow...
@@ -44,49 +42,31 @@ A_USB_LOOPI SUB #1,X                ; 1~        <---+   |  ==> ((65*3)+5)*1000 =
             JNZ A_USB_LOOPJ         ; 2~ 200~ loop -----+
             BIT #RX_TERM,&TERM_IFG  ; 4 new char in TERMRXBUF after A_USB_LOOPJ delay ?
             JNZ A_UART_LOOP         ; 2 yes, the input stream is still active: loop back
-            CALL #INI_FORTH         ; common ?ABORT|RST subroutine
-; ----------------------------------;
-            .word   lit,LINE,FETCH  ; -- f c-addr u line    fetch line number before set ECHO !
-            .word   ECHO            ;
+            CALL #INIT_FORTH        ;                   common ?ABORT|PUC subroutine to init DEFERed definitions
+                                    ;                   cnt is a byte, always positive. If cnt = 0 no RST_RET.
+            .word   DUP             ;
+            .word   QFBRAN,ABORT_END;                       display nothing, don't force ECHO if ABORT" empty string
+            .word   ECHO            ;                       force ECHO
             .word   XSQUOTE         ;
-            .byte   4,27,"[7m"      ;                       type ESC[7m    (set reverse video)
-            .word   TYPE            ;  
-; ----------------------------------;
-            .word   QDUP,QFBRAN     ;                                 do nothing if line = 0
-            .word   ABORT_TYPE      ;
+            .byte   4,27,"[7m"      ;
+            .word   TYPE            ;                       type ESC [7m    (set reverse video)
 ; ----------------------------------;
-; Display error "line:xxx"          ; -- f c-addr u line
+; Display QABORT|WARM message       ; <== WARM jumps here
 ; ----------------------------------;
-            .word   XSQUOTE         ; -- f c-addr u line c-addr1 u1   displays the line where error occured
-            .byte   15,"LAST.4TH, line " ;
-            .word   TYPE            ; -- f c-addr u line
-            .word   UDOT            ; -- f c-addr u
-; ----------------------------------;
-; Display ABORT message             ; <== WARM jumps here
-; ----------------------------------;
-ABORT_TYPE  .word   TYPE            ; -- f              type abort message
+ABORT_TYPE  .word   TYPE            ; -- f                  type QABORT|WARM message
             .word   XSQUOTE         ; -- f c-addr u
             .byte   4,27,"[0m"      ;
-            .word   TYPE            ; -- f              set normal video
-            .word   ABORT           ; no return
-
-
-; ----------------------------------;
-COLD_TERM                           ; default STOP_APP: wait TERMINAL idle
-; ----------------------------------;
-UART_COLD_TERM
-            BIT #1,&TERM_STATW      ;3
-            JNZ COLD_TERM           ;2 loop back while TERM_UART is busy
-            MOV @RSP+,PC            ;  return to software_BOR
+            .word   TYPE            ; -- f                  set normal video
+ABORT_END   .word   ABORT           ; -- f                  no return
 ; ----------------------------------;
 
+;-------------------------------------------------------------------------------
+; INIT TERMinal then enable I/O     ;
+;-------------------------------------------------------------------------------
+UART_INIT_TERM                      ; see MSP430FRxxxx.pat file
 ; ----------------------------------;
-INIT_TERM                           ; TOS = RSTIV_MEM
-; ----------------------------------;
-UART_INIT_TERM                      ;
-    CMP #2,TOS                      ;
-    JNC UART_INIT_TERM_END          ; no INIT_TERM if RSTIV_MEM U< 2 (WARM)
-; ----------------------------------;
+INIT_TERM                           ; TOS = USERSYS, don't change it
+    CALL #COLD_TERM                 ; wait while TERM_UART is busy
     MOV #0081h,&TERM_CTLW0          ; UC SWRST + UCLK = SMCLK
     MOV &TERMBRW_RST,&TERM_BRW      ; init value in FRAM
     MOV &TERMMCTLW_RST,&TERM_MCTLW  ; init value in FRAM
@@ -94,118 +74,129 @@ UART_INIT_TERM                      ;
     BIC #1,&TERM_CTLW0              ; release UC_TERM from reset...
     BIS #WAKE_UP,&TERM_IE           ; then enable interrupt for wake up on terminal input
     BIC #LOCKLPM5,&PM5CTL0          ; activate all previous I/O settings.
-UART_INIT_TERM_END
     MOV @RSP+,PC                    ; RET
 ; ----------------------------------;
 
-
-; ----------------------------------;
-RXON                                ; default BACKGND_APP 
-; ----------------------------------;
-UART_RXON   JMP RXON_EXE            ; Software and/or hardware flow control, to start Terminal UART for one line
-; ----------------------------------;
-
 ; ----------------------------------;
-RXOFF                               ; Software and/or hardware flow control, to stop Terminal UART comunication
+UART_COLD_TERM                      ; default STOP_APP: wait TERMINAL idle
 ; ----------------------------------;
-UART_RXOFF                          ;
-    .IFDEF TERMINAL3WIRES           ;   first software flow control
-RXOFF_LOOP  BIT #TX_TERM,&TERM_IFG  ;3      wait the sending of last char
-            JZ RXOFF_LOOP           ;2
-            MOV #19,&TERM_TXBUF     ;4      move XOFF char into TX_buf
-    .ENDIF                          ;
-    .IFDEF TERMINAL4WIRES           ;   and hardware flow control after
-            BIS.B #RTS,&HANDSHAKOUT ;3     set RTS high
-    .ENDIF                          ;
-            MOV @RSP+,PC            ;4 to CR_NEXT, ...or user defined
+WAIT_UART_IDLE
+COLD_TERM   BIT #1,&TERM_STATW      ;3 uart busy ?
+            JNZ COLD_TERM           ;2 loop back while TERM_UART is busy
 ; ----------------------------------;
-
+UART_INIT_SOFT                      ;
 ; ----------------------------------;
-RXON_EXE
+INIT_SOFT_TERM
+            MOV @RSP+,PC            ; does nothing by default
 ; ----------------------------------;
-    .IFDEF TERMINAL3WIRES           ;   first software flow control
-RXON_LOOP   BIT #TX_TERM,&TERM_IFG  ;3      wait the sending of last char, useless at high baudrates
-            JZ RXON_LOOP            ;2
-            MOV #17,&TERM_TXBUF     ;4  move char XON into TX_buf
-    .ENDIF                          ;
-    .IFDEF TERMINAL4WIRES           ;   and hardware flow control after
-            BIC.B #RTS,&HANDSHAKOUT ;3      set RTS low
-    .ENDIF                          ;
-            MOV @RSP+,PC            ;4  to BACKGND (End of file download or quiet input) or AKEYREAD...
-; ----------------------------------;   ... (get next line of file downloading), or user defined
 
-
-;===============================================================================
-            FORTHWORD "WIPE"        ; software DEEP_RESET
-;===============================================================================
-WIPE        MOV #-1,&RSTIV_MEM      ; negative value ==> DEEP_RESET
-            JMP COLD
-
-;===============================================================================
-            FORTHWORD "COLD"
-;===============================================================================
-;Z COLD     --      performs a software RESET
-; as pin RST is replaced by pin NMI, RESET by pin activation is redirected here via USER NMI vector
-; that allows actions to be performed before executing software BOR.
-COLD        CALL @PC+               ; COLD first calls STOP_APP, in this instance: CALL #COLD_TERM by default
-PFACOLD     .word COLD_TERM         ; INI_COLD_DEF: default value set by WIPE. see forthMSP430FR_TERM_xxxx.asm
-            BIT.B #IO_WIPE,&WIPE_IN ; hardware Deep_RESET request (low) ?
-            JNZ COLDEXE             ; no
-            MOV #-1,&RSTIV_MEM      ; yes, set negative value to force DEEP_RESET
-COLDEXE     MOV #0A504h,&PMMCTL0    ; performs software_BOR, see RESET in forthMSP430FR.asm
-; ----------------------------------;
-
-;-----------------------------------;
-            FORTHWORD "WARM"        ;
-;-----------------------------------;
-;Z WARM     xi --                   ; the end of RESET
-;-----------------------------------;
-WARM                                ;
 ;-------------------------------------------------------------------------------
-; RESET 7: if RSTIV_MEM <> WARM, init TERM and enable I/O
+; UART TERMINAL : WARM SYS COLD
 ;-------------------------------------------------------------------------------
-            CALL @PC+               ; init TERM, only if TOS U>= 2 (RSTIV_MEM <> WARM)
-    .IFNDEF SD_CARD_LOADER          ;
-PFAWARM     .word INIT_TERM         ; INI_HARD_APP default value, init TERM UC, unlock I/O's, TOS = RSTIV_MEM
-    .ELSE
-PFAWARM     .word INI_HARD_SD       ; init SD Card + init TERM, see forthMSP430FR_SD_INIT.asm
-    .ENDIF                          ; TOS = RSTIV_MEM
-;-----------------------------------;
-WARM_DISPLAY                        ; TOS = RSTIV_MEM value
-    ASMtoFORTH
+; ----------------------------------; thanks to INIT_FORTH, WARM implements the choice
+UART_WARM                           ; made by the user with SYS|hardwareRST|DEEP_reset
+;-----------------------------------; regarding the state of the software.
+WARM        CALL &HARD_APP          ;
+            mASM2FORTH              ;
+    .word   ECHO                    ;
     .word   XSQUOTE
     .byte   7,13,10,27,"[7m#"       ; CR + cmd "reverse video" + #
     .word   TYPE
-    .word   DOT                     ; display TOS = RSTIV_MEM value
+    .word   DOT                     ; display TOS = USERSYS value
     .word   XSQUOTE
-    .byte   25,"FastForth ©J.M.Thoorens "
+    .byte   25,"FastForth ",169,"J.M.Thoorens, "
     .word   TYPE
-    .word   LIT,FRAM_FULL,HERE,MINUS,UDOT
+    .word   LIT,FRAM_FULL
+    .word   HEREXEC,MINUS,UDOT
     .word   XSQUOTE
     .byte   10,"bytes free"
-    .word   BRAN,ABORT_TYPE         ; without return
+    .word   BRAN,ABORT_TYPE         ; without return!
+;-----------------------------------;
+
+;-----------------------------------;
+            FORTHWORD "SYS"         ; n --      software RST, DEEP_RST, COLD, WARM
+;-----------------------------------;
+            CMP #0,TOS              ;
+            JL SYSEND               ; if -n SYS  ==> COLD + DEEP_RESET
+            JZ NOPUC                ; if [0] SYS
+            BIT #1,TOS              ;
+            JNC SYSEND              ; if +n SYS (+n even)
+NOPUC       PUSH #WARM              ;
+            PUSH RSP                ; Push address of WARM address
+            JMP INIT_FORTH          ; if +n SYS (+n odd)  ==> INIT_FORTH --> WARM -->  WARM display
+SYSEND      MOV TOS,&USERSYS        ; ==> COLD --> PUC --> INIT_FORTH --> WARM -->  WARM display
+;===============================================================================
+COLD        ; <--- USER_NMI vector <--- <RESET> and <RESET> + <SW1> (DEEP_RESET)
+;===============================================================================
+; as pin RST is replaced by pin NMI, RESET by pin activation is redirected here via USER NMI vector
+; that allows actions to be performed before executing software BOR.
+            CALL &COLD_APP          ; to stop APPlication before reset
+            BIT.B #SW1,&SW1_IN      ; <SW1> pressed ?
+            JNZ COLDEXE             ; no
+            MOV #-1,&USERSYS        ; yes, set negative value to force DEEP_RESET
+COLDEXE     MOV #0A504h,&PMMCTL0    ; performs software_BOR ------------------------+
+;===============================================================================    |
+RESET                               ; <-- RST vect. <-- SYS_failures PUC POR BOR <--+
+;===============================================================================
+; PUC 1: replace pin RESET by pin NMI, stops WDT_RESET
+;-------------------------------------------------------------------------------
+            BIS #3,&SFRRPCR         ; pin RST becomes pin NMI with falling edge, so SYSRSTIV = 4
+            BIS #10h,&SFRIE1        ; enable NMI interrupt ==> hardware RESET is redirected to COLD.
+            MOV #5A80h,&WDTCTL      ; disable WDT RESET
+;-------------------------------------------------------------------------------
+; PUC 2: INIT STACK
+;-------------------------------------------------------------------------------
+            MOV #RSTACK,RSP         ; init return stack
+            MOV #PSTACK,PSP         ; init parameter stack
+;-------------------------------------------------------------------------------
+; PUC 3: I/O, RAM, RTC, CS, SYS initialisation limited to FastForth usage.
+;          All unused I/O are set as input with pullup resistor.
+;-------------------------------------------------------------------------------
+        .include "TargetInit.asm"   ; include target specific init code
+;-------------------------------------------------------------------------------
+; PUC 4: init RAM to 0
+;-------------------------------------------------------------------------------
+            MOV #RAM_LEN,X          ; 2 RAM_LEN must be even and > 1, obviously.
+INITRAMLOOP SUB #2,X                ; 1
+            MOV #0,RAM_ORG(X)       ; 3
+            JNZ INITRAMLOOP         ; 2     6 cycles loop !
+;-------------------------------------------------------------------------------
+; PUC 5: GET SYSRSTIV and SYS_USER  ; X = 0
+;-------------------------------------------------------------------------------
+            MOV &SYSRSTIV,X         ; X <-- SYSRSTIV <-- 0
+            MOV &USERSYS,TOS        ; TOS = USERSYS
+            MOV #0,&USERSYS         ; clear USERSYS
+            AND #-1,TOS             ;
+            JNZ PUC6                ; if TOS <> 0, keep USERSYS value
+            MOV X,TOS               ; TOS <-- SYSRSTIV
+;-------------------------------------------------------------------------------
+; PUC 6: START FORTH engine
+;-------------------------------------------------------------------------------
+PUC6        CALL #INIT_FORTH        ; common part of QABORT|PUC
+PUCNEXT     .WORD WARM              ; no return. May be redirected by BOOT.
+;-----------------------------------;
 
 ;-------------------------------------------------------------------------------
-; INTERPRETER INPUT
+; INTERPRETER INPUT: ACCEPT KEY EMIT ECHO NOECHO
 ;-------------------------------------------------------------------------------
             FORTHWORD "ACCEPT"
+;-----------------------------------;
 ;https://forth-standard.org/standard/core/ACCEPT
 ;C ACCEPT  addr addr len -- addr len'  get line at addr to interpret len' chars
 ACCEPT      MOV @PC+,PC             ;3 Code Field Address (CFA) of ACCEPT
 PFAACCEPT   .word   BODYACCEPT      ;  Parameter Field Address (PFA) of ACCEPT
-BODYACCEPT                          ;  BODY of ACCEPT = default execution of ACCEPT
 ; ----------------------------------;
 ; ACCEPT part I prepare TERMINAL_INT;
 ; ----------------------------------;
-            MOV TOS,X               ;1 -- addr len
+BODYACCEPT  MOV TOS,X               ;1 -- addr len
             MOV @PSP,TOS            ;2 -- org ptr
             ADD TOS,X               ;1 -- org ptr   X = buf_end
             MOV #0Dh,W              ;2              W = 'CR' to speed up char loop in part II
             MOV #20h,T              ;2              T = 'BL' to speed up char loop in part II
             MOV IP,S                ;               S = ACCEPT_ret
-            MOV #CR_NEXT,IP         ;2             IP = XOFF_ret
+            MOV #CR_NEXT,IP         ;2              IP = XOFF_ret
             PUSHM #5,IP             ;5              PUSHM IP,S,T,W,X       r-- XOFF_ret ACCEPT_ret BL CR buf_end
-            JMP SLEEP               ;2              which calls RXON before falling down to LPMx mode
+            JMP SLEEP               ;2
 ; ----------------------------------;
 
 ; **********************************;
@@ -214,18 +205,26 @@ TERMINAL_INT                        ; <--- TEMR RX interrupt vector, delayed by
 ; (ACCEPT) part II under interrupt  ; Org Ptr -- len'
 ; ----------------------------------;
             ADD #4,RSP              ;1  remove SR and PC from stack, SR flags are lost (unused by FORTH interpreter)
-            POPM #4,IP              ;6  POPM W=buffer_bound, T=0Dh, S=20h, IP=ACCEPT_RET r-- XOFF_ret 
-; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
-; starts the 2th stopwatch          ;
-; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
+            POPM #3,IP              ;6  POPM W=buffer_bound, T=0Dh, S=20h, IP=ACCEPT_RET r-- XOFF_ret
+; ----------------------------------;
 AKEYREAD    MOV.B &TERM_RXBUF,Y     ;3  read character into Y, RX_TERM is cleared
 ; ----------------------------------;
             CMP.B T,Y               ;1      CR ?
-            JZ RXOFF                ;2      then RET to CR_NEXT
-; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;+ 12   to send RXOFF
-; stops the first stopwatch         ;=      first bottleneck, best case result: 25~ + LPMx wake_up time..
-; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
-            CMP.B S,Y               ;1      printable char ?
+            JNZ AKEYRDNNEXT         ;2      no
+; ----------------------------------;
+RXOFF                               ; Software|hardware flow control to stop RX UART    r-- ACCEPT_ret CR_NEXT
+; ----------------------------------;
+    .IFDEF TERMINAL3WIRES           ;   first software flow control
+RXOFF_LOOP  BIT #TX_TERM,&TERM_IFG  ;3      wait the sending of last char
+            JZ RXOFF_LOOP           ;2
+            MOV #19,&TERM_TXBUF     ;4      move XOFF char into TX_buf
+    .ENDIF                          ;
+    .IFDEF TERMINAL4WIRES           ;   and hardware flow control after
+            BIS.B #RTS,&HANDSHAKOUT ;3  set RTS high
+    .ENDIF                          ;
+            MOV @RSP+,PC            ;4 to CR_NEXT
+; ----------------------------------;
+AKEYRDNNEXT CMP.B S,Y               ;1      printable char ?
             JC ASTORETEST           ;2      yes
 ; ----------------------------------;
             CMP.B #8,Y              ;1      char = BS ?
@@ -241,37 +240,24 @@ AKEYREAD    MOV.B &TERM_RXBUF,Y     ;3  read character into Y, RX_TERM is cleare
 ; end of backspace                  ;
 ; ----------------------------------;
 ASTORETEST  CMP W,TOS               ; 1 Bound is reached ?
-            JZ YEMIT                ; 2 yes: send echo then loopback
-            MOV.B Y,0(TOS)          ; 3 no: store char @ Ptr, send echo then loopback
+            JC YEMIT                ; 2 yes: don't store char @ Ptr, don't increment TOS
+            MOV.B Y,0(TOS)          ; 3 no: store char @ Ptr
             ADD #1,TOS              ; 1     increment Ptr
 ; ----------------------------------;
 WAITaKEY    BIT #RX_TERM,&TERM_IFG  ; 3 new char in TERMRXBUF ?
             JNZ AKEYREAD            ; 2 yes
-; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
-; stops the 2th stopwatch           ; best case result: 26~/22~ (with/without echo) ==> 385/455 kBds/MHz
-; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
             JZ WAITaKEY             ; 2 no
 ; ----------------------------------;
-
-; ----------------------------------;
 ; return of RXOFF
 ; ----------------------------------;
 CR_NEXT     SUB @PSP+,TOS           ; -- len'
-; ----------------------------------;
-            MOV #LPM0+GIE,&LPM_MODE ;               reset LPM_MODE to default mode LPM0 for next line of input stream
-; ----------------------------------;
 WAITLF      BIT #RX_TERM,&TERM_IFG  ;               char 'LF' is received ?
             JZ WAITLF               ;               no
             MOV.B &TERM_RXBUF,Y     ;               yes, clear RX_int flag after LF received
 ; ----------------------------------;
-ACCEPT_EOL  CMP #0,&LINE            ;               if LINE <> 0 increment LINE             
-            JZ ACCEPT_END           ;
-            ADD #1,&LINE            ;
-ACCEPT_END  
-; ----------------------------------;
-            MOV S,Y                 ;               output a BL on TERMINAL (for the case of error occuring)
-            JMP YEMIT               ;               before interpret line
-; **********************************;
+ACCEPT_EOL  MOV S,Y                 ;               output a BL on TERMINAL (for the case of error occuring)
+            JMP YEMIT               ;               before return to ABORT to interpret line
+; **********************************;               UF9 to UF11 are reset.
 
 ; ------------------------------------------------------------------------------
 ; TERMINAL I/O, input part
@@ -281,9 +267,22 @@ ACCEPT_END
 ; KEY      -- c      wait character from input device ; primary DEFERred word
 KEY         MOV @PC+,PC             ;4  Code Field Address (CFA) of KEY
 PFAKEY      .word   BODYKEY         ;   Parameter Field Address (PFA) of KEY, with default value
-BODYKEY     SUB #2,PSP              ;1  push old TOS..
+BODYKEY     PUSH #KEYNEXT           ;
+; ----------------------------------;
+RXON                                ; default BACKGND_APP
+; ----------------------------------;
+    .IFDEF TERMINAL3WIRES           ;   first software flow control
+RXON_LOOP   BIT #TX_TERM,&TERM_IFG  ;3      wait the sending of last char, useless at high baudrates
+            JZ RXON_LOOP            ;2
+            MOV #17,&TERM_TXBUF     ;4  move char XON into TX_buf
+    .ENDIF                          ;
+    .IFDEF TERMINAL4WIRES           ;   and hardware flow control after
+            BIC.B #RTS,&HANDSHAKOUT ;3      set RTS low
+    .ENDIF                          ;
+            MOV @RSP+,PC            ;4  to BACKGND (End of file download or quiet input) or AKEYREAD...
+; ----------------------------------;   ... (get next line of file downloading), or user defined
+KEYNEXT     SUB #2,PSP              ;1  push old TOS..
             MOV TOS,0(PSP)          ;3  ..onto stack
-            CALL #RXON
 KEYLOOP     BIT #RX_TERM,&TERM_IFG  ; loop if bit0 = 0 in interupt flag register
             JZ KEYLOOP              ;
             MOV &TERM_RXBUF,TOS     ;
@@ -306,18 +305,16 @@ YEMIT      BIT #TX_TERM,&TERM_IFG   ; 3 wait the sending end of previous char, u
 YEMIT1      BIT.B #CTS,&HANDSHAKIN  ;
             JNZ YEMIT1
         .ENDIF
-QYEMIT      .word   48C2h           ;3 48C2h = MOV.B Y,&<next_adr>
-            .word   TERM_TXBUF      ; 3 MOV Y,&TERMTXBUF
+QYEMIT      MOV.B Y,&TERM_TXBUF     ; 3 may be replaced by MOV @IP+,PC with NOECHO
             MOV @IP+,PC             ;
 
             FORTHWORD "ECHO"
 ;Z ECHO     --      connect terminal output (default)
 ECHO        MOV #48C2h,&QYEMIT      ; 48C2h = MOV.B Y,&<next_adr>
-            MOV #0,&LINE            ;
             MOV @IP+,PC
 
             FORTHWORD "NOECHO"
 ;Z NOECHO   --      disconnect terminal output
 NOECHO      MOV #NEXT,&QYEMIT       ;  NEXT = 4030h = MOV @IP+,PC
-            MOV #1,&LINE            ;
             MOV @IP+,PC
+