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