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