-
Notifications
You must be signed in to change notification settings - Fork 12
/
UARTISR
160 lines (137 loc) · 3.57 KB
/
UARTISR
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
\ STM8 eForth buffered UART ISR handler
\ baud rate initialization for UARTISR:
\ 0: default=9600,
\ 1: 2400, 2:4800, 3:9600, 4:19200, 5:57600, 6:115200, 7:230400
#require BUSCTRL
#require :NVM
#require ]B!
#require ]B@IF
#require ]C!
#require OSCFREQ
#require UART_DIV
#require WIPE
\ allow pre-loading STM8 register addresses
#ifndef UART_SR \res MCU: STM8S103
\res export INT_UARTRX INT_UARTTX
\res export UART_SR UART_DR UART_CR2 UART_BRR1
5 CONSTANT #RIEN
6 CONSTANT #TC
6 CONSTANT #TCIEN
7 CONSTANT #TIEN
\ rtbuf: 16 words + 4 bytes protocol
#ifndef BUFLEN 16 ( n ) 2* 4 + CONSTANT BUFLEN
: BR ( br -- ) \ shorthand for baud rate table
OSCFREQ UART_DIV
;
NVM
\ Note: rtbuf, txp and tpb MUST be in the zero page
\ combined RX/TX buffer for n register values in FC03, FC04 and FC16
VARIABLE rtbuf BUFLEN 2- ALLOT
VARIABLE txp \ transmit xfer pointer in ISR
VARIABLE tbp \ transmit buffer pointer
VARIABLE rxp \ receive xfer pointer in ISR
VARIABLE tstamp \ receive timestamp
\ Start UART TX ISR chain
: send ( -- )
BUStx \ enable TX driver
rtbuf txp ! \ next char: buffer start
[ 1 UART_CR2 #TIEN ]B! \ start ISR chain (TXE is active)
;
\ reset TX buffer pointer
: txres ( -- )
rtbuf 2+ tbp ! \ Tx response takes node-id and FC from Rx
;
\ get current transmit buffer pointer
: ctx ( -- a )
tbp @
;
\ TX ISR handler
:NVM
SAVEC
\ txp DUP @ ( va a1 ) DUP ctx < IF
\ Note: rtbuf, txp and tpb MUST be in the zero page
[ $C6 C, UART_SR , \ LD A, UART_SR
$B6 C, txp 1+ C, \ LD A,txp.l
$B1 C, tbp 1+ C, \ CP A,tbp.l
$2A C, \ JRPL
>REL ]
\ ( va a1 ) C@ UART_DR C!
\ ( va ) 1 SWAP +!
[ $92C6 , txp C, \ LD A,[short.w txp]
$C7 C, UART_DR , \ LD UART_DR,A
$3C C, txp 1+ C, \ INC txp.l
]
ELSE
\ ( va a1 ) 2DROP
[ 0 UART_CR2 #TIEN ]B! \ spin down ISR chain
[ 1 UART_CR2 #TCIEN ]B! \ next ISR call: transfer complete
\ test and clear TC ISR
[ UART_SR #TC ]B@IF
\ terminate ISR chain and release bus
[ 0 UART_CR2 #TCIEN ]B!
txres BUSrx
THEN
THEN
IRET
[ OVERT INT_UARTTX !
\ RX ISR handler
:NVM
SAVEC
\ P1H
UART_DR C@
( c ) rxp @ ( c a ) DUP rtbuf - ( c a len ) BUFLEN < IF
( c a ) SWAP ( a c ) OVER ( a c a ) C!
( a ) 1+ rxp !
THEN
TIM tstamp !
\ P1L
IRET
[ OVERT INT_UARTRX !
\ reset RX buffer and initialize RX ISR handler
: rxres ( -- )
rtbuf rxp !
[ 1 UART_CR2 #RIEN ]B!
;
HERE \ pass-on baud rate table address to UARTISR
960 BR , 240 BR , 480 BR , 960 BR , 1920 BR , 5760 BR , 11520 BR , 23040 BR ,
\ initilization of buffered UART handler (call this at least once)
: UARTISR ( n -- )
DUP 0 8 WITHIN NOT IF
DROP 0 \ out of range - use default baud rate
THEN
2* ( BR table ) LITERAL + @ UART_BRR1 !
[ $0C UART_CR2 ]C! \ enable TX and RX
\ PINDEBUG
BUSCTRL
txres rxres
;
\ test if there is enough free space in rtbuf for putting n bytes
: ?txc ( n -- f )
ctx rtbuf - + 1- BUFLEN <
;
\ add c to TX buffer
: txc+ ( c -- )
1 ?txc IF
ctx C! 1 tbp +!
THEN
;
\ add n to TX buffer
: tx+ ( n -- )
2 ?txc IF
ctx ! 2 tbp +!
THEN
;
WIPE RAM
\\ Example, run e.g. in SWIMCOM
#include UARTISR
\ show contents the RX and TX buffers
: bufdump ( -- )
CR ." rtbuf:"
rtbuf rxp @ OVER - DUP . DUMP
;
2 UARTISR
rtbuf BUFLEN 66 FILL
65 rtbuf C!
10 rtbuf BUFLEN 1- + C!
txlen tbp +!
send