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