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