-
Notifications
You must be signed in to change notification settings - Fork 0
/
host-io.fr
223 lines (181 loc) · 7.11 KB
/
host-io.fr
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
\ (c) 2007 Johns Hopkins University / Applied Physics Laboratory
\ Host interface: low-level I/O
\ GAM 2018-09-05 Removed identification with Jedi heritage.
decimal
module> host
\ ------------------------------------------------------------------------
\ Identity
\ ------------------------------------------------------------------------
\ Spacecraft side
\ Variables to control side selection. Note: initially both sides are disabled.
variable side-a
variable side-b
: init-side \ ( -- ) Initialize: turn off transmitters to both sides.
\ GAM 2018-09-10 Enable baud rate clock.
uart-ena-mask# set-io-cfg
iema-enb-mask# \ turn off transmitters
iemb-enb-mask# or clr-io-cfg
;
: side-select \ ( -- ) Select side, if any, to transmit on.
side-a @ if \ if side A active
iema-enb-mask# set-io-cfg \ transmit on side A,
iemb-enb-mask# clr-io-cfg \ but not on side B
else side-b @ if \ otherwise, if side B active
iemb-enb-mask# set-io-cfg \ transmit on side B,
iema-enb-mask# clr-io-cfg \ but not on side A
then then
;
: use-side-a \ ( -- ) Use spacecraft side A. Start listening on side A
\ right now, but transmit on side A on next frame. Delaying
\ prevents possibility of turning on transmitter in middle
\ of a frame.
\ Note: called from an interrupt routine.
iemb-sel-mask# clr-io-cfg \ listen on side A, now
true side-a ! \ transmit on side A, next frame
false side-b ! ;
: use-side-b \ ( -- ) Use spacecraft side B. Start listening on side B
\ right now, but transmit on side B on next frame. Delaying
\ prevents possibility of turning on transmitter in middle
\ of a frame.
\ Note: called from an interrupt routine.
iemb-sel-mask# set-io-cfg \ listen on side B, now
true side-b ! \ transmit on side B, next frame
false side-a ! ;
\ ------------------------------------------------------------------------
\ Telemetry input
\ Input byte queue. Note: space is "stolen" from telemetry.
#rcv-buffer tlm-mem# far-allot \ remotely allocate buffer
constant rcv-buffer \ input buffer
tlm-mem# far-here constant rcv-buffer-end
variable rcv-scan-get \ pointer to next byte to read
variable rcv-scan-put \ pointer to next free slot
variable rcv-count \ number of bytes in buffer
\ Receive/command event semaphore. Semaphore is signalled by bytes
\ received as well as no bytes received timeout (to trigger poll of
\ macros), a real-time command (in case of macro run), and macro commands
\ (to keep macro going).
variable rcv/cmd-event
: cmd-signal \ ( -- ) Signal next command event.
rcv/cmd-event signal ;
: cmd-wait \ ( -- ) Wait for next command event.
rcv/cmd-event wait ;
: handle-rcv \ ( -- ) Handle receive interrupt.
\ Note: called from an interrupt routine.
\ io-mem# set-mem \ remote memory-mapped I/O already set
comm-a# far@ \ read byte from receiver & reset int.
\ Debug point for receiving commands.
\ dup u.
rcv-count @ dup #rcv-buffer <> if \ if room available in input FIFO
1+ rcv-count ! \ count new byte
rcv-scan-put @ dup \ store byte
1+ dup rcv-buffer-end = if drop rcv-buffer then
rcv-scan-put ! \ stepping pointer
tlm-mem# set-mem farc! \ save byte (int. code restores DPR)
cmd-signal \ signal event
else 2drop
then ;
comm-rx-int# int: \ ( -- ) Handle host byte receive interrupt.
handle-rcv \ receive byte
;int
: rcv-empty? \ ( -- t/f ) Return true iff there are no bytes in input buffer.
rcv-count @ 0= ; \ check counter
: rcv-byte \ ( -- byte ) Return next byte.
\ Precondition: rcv-empty? returns false.
get-mem tlm-mem# set-mem \ data in remote memory
disable
rcv-scan-get @ dup farc@ swap \ get byte
1+ dup rcv-buffer-end = if drop rcv-buffer then
rcv-scan-get ! \ step scanner
-1 rcv-count +!
enable
swap set-mem ;
do: timeout-event \ ( -- ) Timeout byte arrival.
cmd-signal ;do
: init-host-input \ ( -- ) Initialize receive. Interrupt is enabled elsewhere.
rcv-buffer rcv-scan-put ! rcv-buffer rcv-scan-get !
timeout-event every 1 seconds doit ;
\ ------------------------------------------------------------------------
\ Telemetry output
\ Transmit data:
2variable xmit-scan \ pointer to next byte
variable xmit-left \ number of bytes remaining
: handle-xmit \ ( -- ) Handle transmit interrupt.
\ Note: called from an interrupt routine.
xmit-left @ ?dup if \ if there is data to send
1- xmit-left ! \ decrement amount left
xmit-scan 2@ set-mem \ send next byte
dup farc@ io-mem# set-mem comm-a# far!
1+ xmit-scan cell+ ! \ step pointer
then ;
comm-tx-int# int: \ ( -- ) Handle host byte transmit interrupt.
handle-xmit ;int \ send byte
: start-frame \ ( addr memid len -- ) Start transmitting given data.
side-select \ select side A or B (or neither)
xmit-left ! xmit-scan 2! \ record length and scan start
get-mem disable \ send first byte to start things going
handle-xmit \ by calling interrupt routine
enable set-mem ;
\ ------------------------------------------------------------------------
\ * Timing
variable 1hz-sem
variable dt-sem
public:
: sync-1hz \ ( -- ) Wait for next 1 Hz pulse.
0 1hz-sem !
1hz-sem wait
0 dt-sem ! ;
: sync-dead-time \ ( -- ) Wait for next dead time.
dt-sem wait ;
private:
1pps-a-int# int: \ ( -- ) Handle host side A tick interrupt.
use-side-a \ use spacecraft side A
sync-time \ synchronize time
;int
1pps-b-int# int: \ ( -- ) Handle host side B tick interrupt.
use-side-b \ use spacecraft side B
sync-time \ synchronize time
;int
timer-int# int: \ ( -- ) Handle timer interrupt. Propogate time, signal
\ dead time, and run milli-schedule.
\ Note: 1Hz signal is delayed from 1PPS. If this were done
\ at the more obvious delta=0, the 1Hz would happen before
\ the 1PPS.
\ Note: schedule call occurs every millisecond, except for
\ 1Hz and dead time's case; this avoids more than one signal
\ per interrupt.
prop-time \ propagate time
[ifdef] __PROTOTYPE__
dup d# 1 = if
1 tickle-up
then
dup d# 501 = if
1 tickle-dn
then
[then]
dup 10 = if
drop 1hz-sem signal \ signal telemetry 1Hz, or
else
d# 800 = if
dt-sem signal
else \ signal telemetry dead time, or
exec-slot \ execute next slot function
then
then
;int
\ ------------------------------------------------------------------------
\ Initialization
: init-host-reg \ ( -- ) Initialize host registers, e.g. baud rate, etc.,
\ and unmask interrupts.
timer-int# get-mask \ unmask timer interrupt,
1pps-a-int# get-mask or \ side A tick,
1pps-b-int# get-mask or \ side B tick,
comm-tx-int# get-mask or \ transmit,
comm-rx-int# get-mask or \ receive,
unmask-int ;
: init-host-io \ ( -- ) Initialize host I/O.
init-side \ initialize side
init-host-input \ initialize input
init-slots
init-host-reg \ unmask interrupts, etc.
;
endmodule>