OSDN Git Service

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