OSDN Git Service

V207 Unlocking IO's moved from COLD to WARM
[fast-forth/master.git] / forthMSP430FR_HALFDUPLEX.asm
1 ; con speed of TERMINAL link, there are three bottlenecks :
2 ; 1- time to send XOFF/RTS_high on CR (CR+LF=EOL), first emergency.
3 ; 2- the char loop time,
4 ; 3- the time between sending XON/RTS_low and clearing UCRXIFG on first received char,
5 ; everything must be done to reduce these times, taking into account the necessity of switching to SLEEP (LPMx mode).
6 ; --------------------------------------;
7 ; (ACCEPT) part I: prepare TERMINAL_INT ;
8 ; --------------------------------------;
9     .IFDEF TOTAL
10             PUSHM   #4,R7               ;6              push R7,R6,R5,R4
11     .ENDIF                              ;
12             MOV     #ENDACCEPT,S        ;2              S = ACCEPT XOFF return
13             MOV     #AKEYREAD1,T        ;2              T = default XON return
14             PUSHM   #3,IP               ;5              PUSHM IP,S,T, as IP ret, XOFF ret, XON ret
15             MOV     TOS,W               ;1 -- addr len
16             MOV     @PSP,TOS            ;2 -- org ptr                                             )
17             ADD     TOS,W               ;1 -- org ptr   W=Bound                                   )
18             MOV     #0Dh,T              ;2              T = 'CR' to speed up char loop in part II  > prepare stack and registers
19             MOV     #20h,S              ;2              S = 'BL' to speed up char loop in part II )  for TERMINAL_INT use
20             BIT     #UCRXIFG,&TERM_IFG  ;3              RX_Int ?
21             JZ      ACCEPTNEXT          ;2              no : case of quiet input terminal
22             MOV     &TERM_RXBUF,Y       ;3              yes: clear RX_Int
23             CMP     #0Ah,Y              ;2                   received char = LF ? (end of downloading ?)
24             JNZ     RXON                ;2                   no : RXON return = AKEYREAD1, to process first char of new line.
25 ACCEPTNEXT  ADD     #2,RSP              ;1                   yes: remove AKEYREAD1 as XON return,
26             MOV     #SLEEP,X            ;2                        and set XON return = SLEEP
27             PUSHM  #4,S                 ;6                        PUSHM S,T,W,X before SLEEP (and so WAKE on any interrupts)
28 ; --------------------------------------;
29 RXON                                    ;
30 ; --------------------------------------;
31     .IFDEF TERMINAL3WIRES               ;
32 RXON_LOOP   BIT     #UCTXIFG,&TERM_IFG  ;3  wait the sending end of XON, useless at high baudrates
33             JZ      RXON_LOOP           ;2
34             MOV     #17,&TERM_TXBUF     ;4  move char XON into TX_buf
35     .ENDIF                              ;
36     .IFDEF TERMINAL4WIRES               ;
37             BIC.B   #RTS,&HANDSHAKOUT   ;4  set RTS low
38     .ENDIF                              ;
39 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
40 ; starts first and 3th stopwatches      ;
41 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
42             RET                         ;4  to SLEEP (End of file download or quiet input) or AKEYREAD1 (get next line of file downloading)
43 ; --------------------------------------;
44
45 ; --------------------------------------;
46 RXOFF                                   ;
47 ; --------------------------------------;
48     .IFDEF TERMINAL3WIRES               ;
49 RXOFF_LOOP  BIT     #UCTXIFG,&TERM_IFG  ;3  wait the sending end of XOFF, useless at high baudrates
50             JZ      RXOFF_LOOP          ;2
51             MOV     #19,&TERM_TXBUF     ;4 move XOFF char into TX_buf
52     .ENDIF                              ;
53     .IFDEF TERMINAL4WIRES               ;
54             BIS.B   #RTS,&HANDSHAKOUT   ;4 set RTS high
55     .ENDIF                              ;
56             RET                         ;4 to ENDACCEPT
57 ; --------------------------------------;
58
59 ; ----------------------------------;
60     ASMWORD "SLEEP"                 ;   may be redirected
61 SLEEP       MOV @PC+,PC             ;3  Code Field Address (CFA) of SLEEP
62 PFASLEEP    .word   BODYSLEEP       ;   Parameter Field Address (PFA) of SLEEP, with default value
63 BODYSLEEP   BIS &LPM_MODE,SR        ;3  enter in LPMx sleep mode with GIE=1
64 ; ----------------------------------;   default FAST FORTH mode (for its input terminal use) : LPM0.
65
66 ;###############################################################################################################
67 ;###############################################################################################################
68
69 ; ### #     # ####### ####### ######  ######  #     # ######  #######  #####     #     # ####### ######  #######
70 ;  #  ##    #    #    #       #     # #     # #     # #     #    #    #     #    #     # #       #     # #
71 ;  #  # #   #    #    #       #     # #     # #     # #     #    #    #          #     # #       #     # #
72 ;  #  #  #  #    #    #####   ######  ######  #     # ######     #     #####     ####### #####   ######  #####
73 ;  #  #   # #    #    #       #   #   #   #   #     # #          #          #    #     # #       #   #   #
74 ;  #  #    ##    #    #       #    #  #    #  #     # #          #    #     #    #     # #       #    #  #
75 ; ### #     #    #    ####### #     # #     #  #####  #          #     #####     #     # ####### #     # #######
76
77 ;###############################################################################################################
78 ;###############################################################################################################
79
80
81 ; here, Fast FORTH sleeps, waiting any interrupt.
82 ; IP,S,T,W,X,Y registers (R13 to R8) are free for any interrupt routine...
83 ; ...and so PSP and RSP stacks with their rules of use.
84 ; remember: in any interrupt routine you must include : BIC #0x78,0(RSP) before RETI
85 ;           to force return to SLEEP.
86 ;           or (bad idea ? previous SR flags are lost) simply : ADD #2 RSP, then RET instead of RETI
87
88
89 ; ======================================;
90             JMP     SLEEP               ;2  here is the return for any interrupts, else TERMINAL_INT  :-)
91 ; ======================================;
92
93
94 ; **************************************;
95 TERMINAL_INT                            ; <--- TEMR RX interrupt vector, delayed by the LPMx wake up time
96 ; **************************************;      if wake up time increases, max bauds rate decreases...
97 ; (ACCEPT) part II under interrupt      ; Org Ptr -- len'
98 ; --------------------------------------;
99              POPM  #5,S                 ;8  POPM  Y=SR,X=PC,W=buffer_bound, T=0Dh,S=20h
100 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
101 ; starts the 2th stopwatch              ;
102 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
103 AKEYREAD    MOV.B   &TERM_RXBUF,Y       ;3  read character into Y, UCRXIFG is cleared
104 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
105 ; stops the 3th stopwatch               ; 3th bottleneck result : 17~ + LPMx wake_up time ( + 5~ XON loop if F/Bds<230401 )
106 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
107 AKEYREAD1                               ; <---  XON RET address 2 ; first emergency: anticipate XOFF on CR as soon as possible
108             CMP.B   T,Y                 ;1      char = CR ?
109             JZ      RXOFF               ;2      then RET to ENDACCEPT
110 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;+ 4    to send RXOFF
111 ; stops the first stopwatch             ;=      first bottleneck (empty line process), best case result: 20~ + LPMx wake_up time..
112 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;       ...or 11~ in case of empty line
113             CMP.B   S,Y                 ;1      printable char ?
114             JHS     ASTORETEST          ;2      yes
115             CMP.B   #8,Y                ;       char = BS ?
116             JNE     WAITaKEY            ;       case of other control chars
117 ; --------------------------------------;
118 ; start of backspace                    ;       made only by an human
119 ; --------------------------------------;
120             CMP     @PSP,TOS            ;       Ptr = Org ?
121             JZ      WAITaKEY            ;       yes: do nothing else
122             SUB     #1,TOS              ;       no : dec Ptr
123             JMP     WAITaKEY
124 ; --------------------------------------;
125 ; end of backspace                      ;
126 ; --------------------------------------;
127 ASTORETEST  CMP     W,TOS               ; 1 Bound is reached ?
128             JZ      WAITaKEY            ; 2 yes: loopback
129             MOV.B   Y,0(TOS)            ; 3 no: store char @ Ptr, send echo then loopback
130             ADD     #1,TOS              ; 1     increment Ptr
131 ; --------------------------------------;
132 WAITaKEY    BIT     #UCRXIFG,&TERM_IFG  ; 3 new char in TERMRXBUF ?
133             JNZ     AKEYREAD            ; 2 yes
134             JZ      WAITaKEY            ; 2 no
135 ; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv;
136 ; stops the 2th stopwatch               ; best case result: 23~ ==> 434 kBds/MHz
137 ; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
138 ; --------------------------------------;
139 ENDACCEPT                               ; <--- XOFF return address
140 ; --------------------------------------;
141             MOV #LPM0+GIE,&LPM_MODE     ; reset LPM_MODE to default mode LPM0 for next line of input stream
142             CMP #0,&LINE                ; if LINE <> 0...
143             JZ ACCEPTEND                ;
144             ADD #1,&LINE                ; ...increment LINE
145 ACCEPTEND   SUB @PSP+,TOS               ; Org Ptr -- len'
146             MOV @RSP+,IP                ; 2 and continue with INTERPRET with GIE=0.
147                                         ; So FORTH machine is protected against any interrupt...
148     .IFDEF TOTAL
149              POPM  #4,R7                ;6              pop R4,R5,R6,R7
150     .ENDIF
151             mNEXT                       ; ...until next falling down to LPMx mode of (ACCEPT) part1,
152 ; **************************************;    i.e. when the FORTH interpreter has no more to do.
153
154 ; ------------------------------------------------------------------------------
155 ; TERMINAL I/O, output part
156 ; ------------------------------------------------------------------------------
157
158
159 ;https://forth-standard.org/standard/core/EMIT
160 ;C EMIT     c --    output character to the output device ; deferred word
161             FORTHWORD "EMIT"
162 EMIT        MOV @PC+,PC             ;3  15~
163 PFAEMIT     .word   BODYEMIT        ;  Parameter Field Address (PFA) of EMIT, with its default value
164 BODYEMIT    MOV TOS,Y               ; 1
165             MOV @PSP+,TOS           ; 2
166 YEMIT1      BIT #UCTXIFG,&TERM_IFG  ; 3 wait the sending end of previous char, useless at high baudrates
167             JZ YEMIT1               ; 2
168     .IFDEF TERMINAL5WIRES           ;
169 YEMIT2      BIT.B #CTS,&HANDSHAKIN  ;
170             JNZ YEMIT2
171     .ENDIF
172 YEMIT       .word   4882h           ; hi7/4~ lo:12/4~ send/send_not  echo to terminal
173             .word   TERM_TXBUF      ; 3 MOV Y,&TERMTXBUF
174             mNEXT                   ; 4
175