chiark / gitweb /
various variable initialisations
[trains.git] / detpic / mascan.asm
1 ;======================================================================
2 ; MASTER - SCANNING ETC.
3
4  include common.inc
5
6 ;----------------------------------------------------------------------
7  udata_acs
8
9 ; for reading and detection:
10 b       res     1       ; byte just read
11 cslot   res     1       ; current slave in slave table, points to flags byte
12 cbyte   res     1
13         ; one of the following:
14         ;       0000 0000       we're expecting the first byte
15         ;       M0B1 0000       we're expecting more detection byte 1
16         ;       M010 0000       we're expecting more detection byte 2
17         ;       1000 0000       we're expecting an extra byte
18         ;       ???? ???1       reading halted due to lack of buffer space:
19 cbyte_halted equ 0 ; also set briefly while we decide what to do next
20
21 wslave                  res 1 ; slave we need to write to
22 outmsg_targetlen        res 1 ; 
23
24 ;======================================================================
25 ; HANDLING OF I2C EVENTS
26
27 near_getwritebyteyes code
28 ;----------------------------------------
29 i2c_getwritebyte_yes
30         pop             ; we don't care where we were in i2cmu_write_next_byte
31         bc_f    STATUS, Z       ; yes, we want to write this byte
32         return          ; from i2cmu_write_next_byte
33         
34  code
35 ;----------------------------------------
36 i2cmu_write_next_byte
37         ; add calls to getwritebyte_<foo> here:
38         call    polarity_getwritebyte
39         call    points_getwritebyte
40         ; end of list of calls to getwritebyte_<foo>
41         ; so, no-one wants this slave:
42         bs_f    STATUS, Z
43         return
44
45 ;----------------------------------------
46 i2cm_intrl
47 ; handles i2c interrupt using i2cm_interrupt[_definite],
48 ; according to the rules for <something>_intrl.
49         bt_f_if0 PIR1, SSPIF
50         return
51         call    i2cm_interrupt_definite
52         intrl_handled_nostack
53
54 ;======================================================================
55 ; PROCESSING OF INCOMING BYTES - CORE AND DETECTION
56
57 ;----------------------------------------
58 i2cmu_read_got_byte
59 ;               Beforehand      At call
60 ;   State       Reading         Reading-Wait
61 ;   W                           data from slave
62 ;
63 ; See detect.asm head comment for protocol info, in particular
64 ; the meaning of these bytes.
65                                 ; W =           received byte
66         mov_wf  b               ; W = b =       received byte
67
68         mov_lfsr slavetable, 1
69         mov_ff  cslot, FSR1L    ; FSR1 ->       slave's flags
70
71         tst_f_ifnz cbyte
72         bra     read_got_notfirst
73         ; this is a first (head) byte:
74
75         bt_f_if0 POSTINC1, stf_detect ; FSR1 -> detbasel
76         bra     read_got_first_reversers
77 read_got_first_detectors        ; b =           MdBBdddd
78         and_lw  0xb0            ; W =           M0BB0000
79         mov_wf  cbyte           ; cbyte =       M0BB0000
80         mov_lw  0x4f            ; W =           01001111
81         and_wff b               ; b =           0d00dddd
82         mov_fw  POSTINC1        ; W = detbasel; FSR1 -> lastd0
83         rcall   read_got_detectbyte_prep ; b =  0d00dddd
84                                          ; u =  0C00CCCC
85         bt_f_if1 b, 6           ; b bit         .d......
86         bs_f    b, 4            ; b =           0d0ddddd
87                                 ;                ^ ^ copies of same bit
88                                 ; u = (still)   0C00CCCC
89                                 ; or, using detection segment bit numbers:
90                                 ; b =           z4z43210
91                                 ; u =           z4zz3210
92         goto    addmsgs_dethead
93
94 ;----------
95 read_got_first_reversers
96         bt_f_if1 b, 6
97         bra     read_got_bad_first_reversers
98         and_lw  0x80            ; W =           M0000000
99         mov_wf  cbyte           ; cbyte =       M0000000
100         bc_f    b, 7            ; b =           00dddddd
101         mov_fw  POSTINC1        ; W = detbasel; FSR1 -> lastd0
102         rcall   read_got_detectbyte_prep
103         goto    addmsgs_revhead
104
105 ;-----
106 read_got_bad_first_reversers panic morse_MR
107
108 ;----------
109 read_got_detectors_b1           ; b =           dddddddd
110         bc_f    cbyte, 4        ; cbyte =       M0B00000
111         mov_fw  POSTINC1        ; W = detbasel; FSR1 -> lastd0
112         inc_f   FSR1L           ; FSR1 -> lastd1
113         add_lw  5               ; W = detbasel+8
114         rcall   read_got_detectbyte_prep
115         goto    addmsgs_all
116
117 ;----------
118 read_got_detectors_b2           ; b =           dddddddd
119         bc_f    cbyte,5         ; cbyte =       M0000000
120         mov_fw  POSTDEC1        ; W = detbasel; FSR1 -> flags
121         bs_f    FSR1L, 2        ; FSR1L ->      lastd2
122         add_lw  13              ; W = detbasel+16
123         rcall   read_got_detectbyte_prep
124         goto    addmsgs_all
125
126 ;----------
127 read_got_detectbyte_prep_ifsomething
128 ;
129 ; This is a branch of read_got_detectbyte_prep, called if we're doing
130 ; `return' rather than `pop+return'.  For conditions on return, see
131 ; read_got_detectbyte_prep; these are supposed to be (basically) the
132 ; same as the entry conditions for addmsgs_<kind>.
133 ;
134 ;               on entry
135 ;  W            [C0]*
136 ;  t            adjdetbasel
137 ;  u            undefined
138 ;  b            [d0]*
139 ;  lastd<n>     [o0]*
140 ;  FSR1 ->      lastd<n>
141 ;
142         mov_wf  u               ; u =           [C0]*
143         xor_wfw INDF1           ; lastd<n> =    [d0]*
144         mov_lw  0x07
145         ior_wff FSR1L           ; FSR1L ->      detmsgh
146         return ; to addmsgs_<something>, very shortly
147
148 ;----------------------------------------
149 read_got_notfirst
150         bt_f_if1 cbyte, 4
151         bra     read_got_detectors_b1
152         bt_f_if1 cbyte, 5
153         bra     read_got_detectors_b2
154         ; it must be an extra byte
155
156         bt_f_if0 b, 7           ; any more ?
157         bc_f    cbyte, 7
158         bc_f    b, 7
159         call    process_got_extra
160         bra     i2c_arrange_next_byte
161
162 ;----------
163 read_got_detectbyte_prep
164 ;
165 ; Sees if anything has changed.  If no changes pops one return address
166 ; and branches to i2c_arrange_next_byte; if some changes, returns to
167 ; calling point.
168 ;
169 ; So, caller should be i2cmu_read_got_byte, and next stuff
170 ; should basically be a call to addmsg_<something> (perhaps preceded
171 ; by a bit of fiddling of b).  addmsg_<something> will finish
172 ; by branching to i2c_arrange_next_byte.
173 ;
174 ;               call                    return          pop+return
175 ;  W            adjdetbasel             preserved       undefined
176 ;  b            [d0]*                   preserved       preserved
177 ;  FSR1 ->      lastd<n>                detmsgh         preserved
178 ;  cbyte        set for next read etc.  preserved       preserved
179 ;  u            undefined               [C0]*           preserved
180 ;  lastd<n>     [o0]*                   [d0]*           preserved = [d0]*
181 ;
182 ;  TOS ->       (optionally, fiddle b, and then:) goto addmsgs_<something>
183 ;  NOS          return address for i2cmu_read_got_byte
184 ;
185         mov_wf  t               ; t =           adjdetbasel
186         mov_fw  b               ; W =           [d0]*
187         xor_wfw INDF1           ; W =           [C0]*, Z iff same
188                         ;  where C set iff change to that detection segment
189         bra_nz  read_got_detectbyte_prep_ifsomething
190         ; there's nothing to do
191         pop
192 ;...
193 ;----------------------------------------
194 i2c_arrange_next_byte
195         tst_f_ifnz cbyte
196         goto    i2cm_read_another
197 ;...
198 ;======================================================================
199 ; DECIDING WHICH SLAVE TO ADDRESS
200 ;...
201 i2c_arrange_something
202 ; figure out what to do next - which pic to address, etc.
203         bs_f    cbyte, cbyte_halted
204
205         tst_f_ifnz wslave       ; anyone asked to write ?
206         bra     arrange_write
207 nextslave_nowrite
208         ; no writing needed, we consider reading:
209         neg_fw  outmsg_begin
210         add_wfw outmsg_end
211         and_lw  outbuf_size - 1
212         cmp_fw_ifle outmsg_targetlen
213         return ; target len < actual len, do not add anything
214         ; ok, there's space, go ahead:
215         bc_f    cbyte, cbyte_halted
216
217         mov_lw  ste_size
218         add_wff cslot           ; cslot -> next ste_flags
219         mov_lfsr slavetable, 1  ; FSR1H -> slavetable
220         mov_ff  cslot, FSR1L    ; FSR1 -> new ste_flags
221
222         bt_f_if1 POSTDEC1, stf_sentinel ; FSR1 -> ste_slave
223         bra     nextslave_looparound
224         ; Ok, we have a slave:
225
226         mov_fw  INDF1           ; W = new slave number
227         goto    i2cm_read_start
228
229 nextslave_looparound
230         ; now we do our own detection
231         mov_lw  (slavetable + ste_flags) & 0xff ; select our own slot
232         mov_wf  cslot
233         call    read_detection_head_master
234         goto    i2cmu_read_got_byte
235
236 ;----------------------------------------
237 i2cmu_done
238         ; So we've done one write.
239         bs_f    cbyte, cbyte_halted
240
241         tst_f_ifnz wslave       ; anyone asked in the meantime ?
242         bra     arrange_write
243
244         ; Anyone else to write to ?
245         ; add calls to needwrite_<foo> here:
246         call    polarity_needwrite
247         call    points_needwrite
248         ; end of list of calls to needwrite_<foo>
249
250         ; no, if we're here, no-one wants to write
251         bra     nextslave_nowrite
252
253 ;----------------------------------------
254 i2c_needwrite
255 ; Informs mascan that we need to write to some slave.
256 ; Some time after this, mascan will call getwritebyte_<everything>
257 ; and this must yield at least one byte to write.
258 ;  W            slave that we must write to
259         mov_wf  wslave
260         bt_f_if0 cbyte, cbyte_halted
261         return ; we're currently doing something
262 ;...    
263 ;----------
264 arrange_write
265 ;  wslave       slave to write to
266         bc_f    cbyte, cbyte_halted
267         mov_fw  wslave
268         mov_wf  cwslave
269         clr_f   wslave
270         goto    i2cm_write_start
271
272 ;----------------------------------------
273 i2c_consider_restartread
274         bt_f_if0 cbyte, cbyte_halted
275         return
276         bra     nextslave_nowrite
277
278 ;======================================================================
279 ; INITIALISATION
280
281 mascan_init
282         mov_lw  slavetable & 0xff
283         mov_wf  cslot
284         clr_f   cbyte
285         bs_f    cbyte, cbyte_halted ; serial output of `hello' will start us up
286         clr_f   wslave
287
288         mov_lw  2
289         mov_lfsr slavetable, 0          ; FSR0 -> slavetable
290         load_tblptr pic2detinfo         ; TBLPTR* -> pic2detinfo
291         clr_f   t                       ; t = loop counter
292 mascan_init_loop
293         tblrd_postinc_fixup             ; TABLAT = EOOOOSSS
294         mov_fw  TABLAT                  ; W = EOOOOSSS, N = E
295
296         tblrd_postinc_fixup             ; TABLAT = DSSSSSSS, N (still) = E
297         bra_nn  mascan_init_ifabsent
298
299         mov_ff  t, POSTINC0             ; ste_slave = slave
300         mov_wf  u                       ; u = 1OOOOSSS
301         and_lw  0x78
302         bra_nz  mascan_bad_detinfo0
303         ; ok                            ; u = 10000SSS
304
305         mov_fw  TABLAT                  ; W = DSSSSSSS
306         and_lw  0x80                    ; W = D0000000
307         mov_wf  POSTINC0                ; ste_flags = D0000000
308
309         mov_fw  TABLAT                  ; W = DSSSSSSS
310         bc_w    7                       ; W = 0SSSSSSS = first
311         add_lw  -0xf8                   ; W = first - 0xf8 = detbasel
312         mov_wf  POSTINC0                ; detbasel
313
314         clr_f   POSTINC0                ; lastd0
315         clr_f   POSTINC0                ; lastd1
316         clr_f   POSTINC0                ; lastd2
317         set_f   POSTINC0                ; unused
318
319         mov_fw  u                       ; W = 10000SSS
320         xor_lw  b'10011000' ^ 0x80      ; W = detmsgh
321         mov_wf  POSTINC0                ; detmsgh
322
323 mascan_init_ifabsent
324         inc_f   t                       ; next slave
325         bt_f_if0 t, maxpics_ln2
326         bra     mascan_init_loop
327         ; we've read the whole flash table
328
329  if slavetable == 0x400
330         bt_f_if1 FSR0H, 0
331         bra     mascan_bad_toomany
332  endif
333
334         clr_f   POSTINC0                ; ste_slave
335         mov_lw  (1<<stf_detect)|(1<<stf_sentinel)
336         mov_wf  POSTINC0                ; ste_flags
337         ; rest of final entry, and rest of table, is undefined
338
339         ; at 9600, it's about 1ms per char.
340         ; we allow 1ms to scan 2 pics via i2c.
341         ; so our target len is (no of pics)/2
342         ; plus 2 bytes of slop
343         rl_fw   t
344         add_lw  2
345         mov_wf  outmsg_targetlen
346
347         return
348
349 mascan_bad_detinfo0 panic morse_DF
350 mascan_bad_toomany panic morse_DG
351
352 ;======================================================================
353 ; PROCESSING OF INCOMING BYTES - EXTRA (NON-DETECTION)
354
355 near_gots code
356 ;----------------------------------------
357 process_got_extra
358         mov_fw  b
359 loopback_read_byte
360 ;...
361 ;  W            message
362         xor_lw  0x00 ^ 0x20
363         bra_z   got_pointed
364         xor_lw  0x20 ^ 0xb0
365         bra_z   got_aargh
366         panic   morse_MX
367
368 ;======================================================================
369 ; GENERATION OF DETECTION MESSAGES FOR HOST - MAD BT_F_IF1 TABLES
370
371 addmsg_testbit macro bit
372         bt_f_if1 u, bit
373         rcall   addmsg_one
374         endm
375
376 addmsg_return macro dummy_bit
377         goto    i2c_arrange_next_byte
378         endm
379
380 addmsg_ignore macro dummy_bit
381         nop
382         nop
383         endm
384
385 addmsg_padding macro dummy_bit
386         nop
387         mov_lw  dummy_bit
388         endm
389
390 ;----------------------------------------
391 ;addmsgs_<kind>
392 ;
393 ;                       on entry        after first addmsg_one, or when done
394 ;  W, STATUS, v, FSR0   undefined       trashed
395 ;  t                    adjdetbasel     not modified by addmsgs_<kind> or _one
396 ;  u                    [C0]*           not modified by addmsgs_<kind> or _one
397 ;  b                    [d0]*           not modified by addmsgs_<kind> or _one
398 ;  lastd<n>             [d0]* (new)     not modified by addmsgs_<kind> or _one
399 ;  FSR1 ->              detmsgh         not modified by addmsgs_<kind> or _one
400 ;  outbuf, outmsg_*     not full, updated appropriately
401 ;  all others           any             not interfered with
402 ;  
403 ; (this is all set up by read_prep_detectbyte and
404 ;  read_got_detectbyte_prep_ifsomething)
405 ; when done, branches to i2c_arrange_next_byte, rather than returning
406
407 addmsgs_section code (          7       )*4 + 0x2100
408 ;
409 ;                               A
410 ;                               |- PCL bbb value after macro - number in this
411 ;                               V       column should increment 1 each line
412 ;
413 addmsgs_revhead addmsg_testbit  0
414                 addmsg_testbit  1
415                 addmsg_testbit  2
416                 addmsg_testbit  3
417                 addmsg_testbit  4
418                 addmsg_testbit  5
419                 addmsg_return   6
420
421 addmsgs_all     addmsg_testbit  7
422                 addmsg_testbit  0
423                 addmsg_testbit  1
424                 addmsg_testbit  2
425                 addmsg_testbit  3
426                 addmsg_testbit  4
427                 addmsg_testbit  5
428                 addmsg_testbit  6
429                 addmsg_return   7
430
431 addmsgs_dethead addmsg_testbit  0
432                 addmsg_testbit  1
433                 addmsg_testbit  2
434                 addmsg_testbit  3
435                 addmsg_testbit  6 ; bit 6 was copied to 4 but only in b, not u
436                 addmsg_return   5
437
438 ;----------
439 addmsg_one
440 ;  TOS - 4 ->   bt_f_if1 w, b'bbb'
441 ;  TOSL         ???bbb00
442 ; other conditions on entry and exit as for entry to addmsgs_<kind>, above
443         rr_fw   TOSL            ; W =           0???bbb0
444         rr_w                    ; W =           00???bbb
445         ior_wfw 0xf8            ; W =           11111bbb
446         mov_wf  FSR0L           ; FSR0L =       11111bbb
447         clr_f   FSR0H           ; FSR0 ->       bitnum2bit[bbb]
448         add_wfw t               ; W =           adjdetbasel + 11111bbb
449                                 ;  ie =         0 SSSSSSS (det msg low byte)
450         mov_wf  v               ; v =           0 SSSSSSS (det msg low byte)
451
452         mov_fw  b               ; W =           [d0]*
453         and_wfw INDF0           ; train: W = 0x00, Z=1; none: W = 0*d0*, Z=0
454         bt_f_if0 STATUS, Z
455         mov_lw  0x08            ; train: W = 0 000 0 000; none: W = 0 000 1 000
456         xor_wfw INDF1           ; W =           1 001 Y SSS (det msg high byte)
457         call    serial_addbyte
458
459         mov_fw  v               ; W =           0 SSSSSSS (det msg low byte)
460         goto    serial_addbyte_another
461
462 ;======================================================================
463  include final.inc