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