chiark / gitweb /
still better peco curve
[trains.git] / detpic / detect.asm
1 ;======================================================================
2 ; DETECTION AND SLAVE I2C
3
4 ; FSR1 is used as pointer to where to add bytes of message; it
5 ;  points to previous byte whose top bit must be set before
6 ;  adding another bit
7
8 ; FSR2 is used as readout pointer
9
10   include common.inc
11
12 ; I2C protocol is as follows:
13 ;
14 ;  Master periodically polls each slave, addressing it for reading.
15 ;  The slave replies with the first byte of a self-delimiting message.
16 ;  The master must then read the whole message before doing anything
17 ;  else on the bus.
18 ;
19 ;  First byte is like this:
20 ;       MM 05 B2 B1  10 13 16 08        (detectors)
21 ;       MM zz 01 02  03 00 04 05        (reversers)
22 ;  where
23 ;       B1 and B2 indicates that the is more detection data;
24 ;               each bit corresponding to a subsequent byte:
25 ;               if the bit is set the byte is present; otherwise
26 ;               it is skipped and the contents can be presumed
27 ;               to be the same as last time (initially: 0)
28 ;       zz      is a zero bit
29 ;       MM      indicates that there are extra message byte(s)
30 ;       two digits indicates that the bit is the corresponding
31 ;               detection information.  The bit is clear iff current
32 ;               was detected since the last poll by the master.
33 ;               The bit value is not defined for unused sense
34 ;               segments.
35 ;
36 ;  Following that are the zero, one or two more bytes of
37 ;  detection data:
38 ;       19 09 12 15  18 04 20 17        iff reversers and B1 was set
39 ;       06 01 07 02  11 14 03 00        iff reversers and B2 was set
40 ;
41 ;  Finally, zero or more bytes of extra messages:
42 ;       MM XX XX XX  XX XX XX XX
43 ;  where
44 ;       MM      indicates that further extra message bytes follow;
45 ;               it is clear iff this is the last extra message byte.
46 ;       XX      are the lower 7 bits of a POINTED
47 ;               or AAARGH message (see README.protocol).
48
49 ; Master may also write to slave.  Every written byte is independent:
50 ;
51 ;       11RRRRRR        Set reverse to RRRRRR, see reverse.asm
52 ;       100PPPPP        Fire point PPPPP
53 ;
54 ;       00000000        Acknowlege that slave has crashed, and
55 ;                        switch into crash readout mode
56
57 ;======================================================================
58 ; variables and memory organisation
59
60 max_messages equ 4
61
62   udata_acs
63
64 unattendedl     res     1       ; counts up; each det loop it is
65 unattendedh     res     1       ; incremented by no. of bytes of pc in
66 unattendedu     res     1       ; det loop; if it overflows, led is set to red
67
68 scana           res     1 ; see bit-twiddling below
69 scanb           res     1
70 scanc           res     1
71 scand           res     1
72 scane           res     1
73
74 last1           res     1
75 last2           res     1
76
77 buf0_startval           res     1 ; reversers start with some det bits
78 buf0                    res     1
79 message_buffer          res     max_messages
80 message_buffer_end      res     0
81
82 ;----------------------------------------------------------------------
83 ; buf0, message_buffer, and FSR1 are used mainly for recording
84 ; non-detection messages.  They look like this:
85 ;
86 ;  +--------+--------+--------+--------+--------+
87 ;  |  buf0  | message_buffer...                 |
88 ;  +--------+--------+--------+--------+--------+
89 ;
90 ;  |0d0d0000|???????? ???????? ???????? ????????|   no extra messages
91 ;   ^
92 ;  |1d0d0000|0aaaaaaa ???????? ???????? ????????|   one extra byte
93 ;            ^
94 ;  |1d0d0000|1aaaaaaa 0bbbbbbb ???????? ????????|   two extra bytes
95 ;
96 ; etc.    Bits labelled `d' are detection data on reversers boards
97 ;          0 on detectors boards; `a' and `b' are extra message data;
98 ;          `^' indicates the byte pointed to by FSR1
99 ;
100 ;----------------------------------------------------------------------
101 ;
102 ; outbuf and FSR2 are used (on slaves) for the message we are
103 ; transmitting.  FSR2 points to the next byte to transmit (ie, which
104 ; will be read).  outmsg_end points to the first byte after the
105 ; message, and is used for read overrun detection.
106 ;
107 ; During i2csu_read_begin (High ISR), the actual first byte of the
108 ; message to be sent is calculated from buf0, and transmitted; the
109 ; extra detection bytes (if any) are stored in outbuf, and any extra
110 ; messages (from message_buffer) are also appended to outbuf.
111 ;
112 ;======================================================================
113         code
114
115 ;----------
116 detect_local_init @
117         mov_lw  b'111'  ; turn off comparator, or we can't use pins
118         mov_wf  CMCON   ;   RD0-RD4 as digital inputs
119         mov_lw  b'0110' ; turn off A/D except perhaps for pin
120         ior_wff ADCON1  ;   AN0 ie SPARE ie RA0 (same reason as above)
121
122         ; compute buf0_startval
123         clr_w
124         bt_f_if0 idloc1,idloc1_boarddet
125         mov_lw  0x14 ; see under reversers, below
126         mov_wf  buf0_startval
127
128         set_f   scana
129         set_f   scanb
130         set_f   scanc
131         set_f   scand
132         set_f   scane
133         set_f   last1
134         set_f   last2
135         mov_ff  buf0_startval, buf0
136
137         return
138
139 ;----------
140 detect_slave_init @
141         mov_lfsr outbuf, 2
142         clr_f   outmsg_end
143
144         goto    reset_detectread
145
146 ;----------------------------------------
147 slave_add_short_message @
148 ; Queues a message byte for transmission to the master.
149 ; It will be transmitted as an extra message byte, when we are polled.
150 ;  W            message         unchanged
151 ;  GIEH         set             set
152         intrh_mask
153         bs_f    INDF1,7
154         mov_wf  PREINC1
155         intrh_unmask
156
157         mov_lw  message_buffer_end-1
158         cmp_fw_ifle FSR1L
159         return
160
161         panic   morse_DB
162
163 ;----------
164 backgroundloop_again macro backgroundloop_whatever
165   local branchposition
166         inc_f_ifnz unattendedl
167         bra     backgroundloop_whatever
168         mov_lw  branchposition - backgroundloop_whatever
169 branchposition
170         add_wff unattendedh
171         bra_nc  backgroundloop_whatever
172         inc_f_ifz unattendedu
173         call    led_red
174         bra     backgroundloop_whatever
175         endm
176
177 near_i2csu code
178 ;----------
179 i2csu_read_begin
180 ; called from High ISR, see i2clib.inc
181         bt_f_if1 idloc1,idloc1_boarddet
182         bra     i2csu_read_begin_detectors
183         bra     i2csu_read_begin_reversers
184
185 ;----------
186 i2csu_read_another
187 ; called from High ISR, see i2clib.inc
188         mov_fw  POSTINC2
189         i2cs_read_data_macro
190         mov_fw  outmsg_end
191         cmp_fw_ifle FSR2L
192         return
193         ; oops
194         panic   morse_DR
195
196 ;======================================================================
197 ; main detection bit-twiddling
198
199                         ;       80 40 20 10  08 04 02 01
200                         ;        7  6  5  4   3  2  1  0
201
202 ;----------------------------------------------------------------------
203 ; detectors
204
205                         ; A     xx 19 09 12  15 18 xx xx
206                         ; B     xx xx xx 04  20 17 xx xx
207                         ; C     xx xx 05 xx  xx 10 13 16
208                         ; D     02 11 14 xx  08 xx 01 07
209                         ; E     xx xx xx xx  xx 03 00 06
210
211                         ; buf0  MM zz B2 B1  zz zz zz zz
212
213                 ; scheme for bit shuffling:
214                 ;
215                 ; 1:    ; _<A   19 09 12 15  18 xx xx xx
216                 ;       ; >>B   xx xx xx xx  xx 04 20 17
217                 ;
218                 ; 2:    ; _>E   06 xx xx xx xx  xx 03 00
219                 ;       ; [*D   xx 01 07 02  11 14 xx ??        C=08
220                 ;
221                 ; 0:    ; [_C   xx 05 xx xx  10 13 16 08
222                 ;
223 ;               ; where _ means do nothing
224                 ;       *       swap nybbles
225                 ;       <       rotate left
226                 ;       >       rotate right
227                 ;       [       rotate left through carry (NB
228                 ;                that the carry bit propagates to
229                 ;                the subsequent [ or ] *in the
230                 ;                same column*).
231                 ; and the operation done first (in backgroundloop)
232                 ; is on the right next to the port letter and the one
233                 ; done second (in i2csu_read_begin_...) is shown
234                 ; on the left, above.
235
236 ;----------
237 backgroundloop_detectors @
238         rr_fw   PORTB   ; W     xx xx xx xx  04 20 17 xx (now)
239         and_wff scanb   ; b     xx xx xx xx  04 20 17 xx (cumulative)
240         rl_fw   PORTA   ; W     19 09 12 15  18 xx xx xx (now)
241         and_wff scana   ; a     19 09 12 15  18 xx xx xx (cumulative)
242
243         rr_fw   PORTE   ; W     06 xx xx xx  xx xx 03 00 (now)
244         and_wff scane   ; e     06 xx xx xx  xx xx 03 00 (cumulative)
245         swap_fw PORTD   ; W     08 xx 01 07  02 11 14 xx (now)
246         and_wff scand   ; d     08 xx 01 07  02 11 14 xx (cumulative)
247
248         mov_fw  PORTC   ; W     xx xx 05 xx  xx 10 13 16 (now)
249         and_wff scanc   ; c     xx xx 05 xx  xx 10 13 16 (cumulative)
250
251         backgroundloop_again backgroundloop_detectors
252
253 ;----------             ; buf0  MM zz zz zz  zz zz zz zz
254 i2csu_read_begin_detectors
255   ; detection byte 1
256         mov_lw  0xf8    ; W     yy yy yy yy  yy zz zz zz
257         and_wff scana   ; scana 19 09 12 15  18 zz zz zz
258
259         rr_fw   scanb   ; W     xx xx xx xx  xx 04 20 17
260         and_lw  0x07    ; W     zz zz zz zz  zz 04 20 17
261         ior_wff scana   ; scana 19 09 12 15  18 04 20 17
262
263         mov_fw  scana
264         cmp_fw_ifne last1
265         bs_f    buf0,4  ; buf0  MM zz zz B1  zz zz zz zz
266
267   ; detection byte 2
268         mov_lw  0x83    ; W     yy zz zz zz  zz zz yy yy
269         and_wff scane   ; scane 06 zz zz zz  zz zz 03 00
270
271         rlc_fw  scand   ; W     xx 01 07 02  11 14 xx xx  C=08
272         and_lw  0x7c    ; W     zz 01 07 02  11 14 zz zz  C=08
273         ior_wff scane   ; scane 06 01 07 02  11 14 03 00  C=08
274
275         mov_fw  scane
276         cmp_fw_ifne last2
277         bs_f    buf0,5  ; buf0  MM zz B2 B1  zz zz zz zz
278
279   ; detection and lead byte, 0
280         rlc_fw  scanc   ; W     xx 05 xx xx  10 13 16 08
281         and_lw  0x4f    ; W     zz 05 zz zz  10 13 16 08
282         ior_wfw buf0    ; W     MM 05 B2 B1  10 13 16 08
283
284         i2cs_read_data_macro
285
286         rcall   new_i2c_outmsg
287
288         mov_fw  scana
289         bt_f_if1 buf0,4
290         mov_wf  POSTINC2
291         mov_wf  last1
292
293         mov_fw  scane
294         bt_f_if1 buf0,5
295         mov_wf  POSTINC2
296         mov_wf  last2
297
298         set_f   scanb
299         set_f   scanc
300         set_f   scane
301
302 ;...
303 ;----------------------------------------------------------------------
304 ; both detectors and reversers
305 ;
306 i2csu_read_begin_either_tail
307         set_f   scana
308         set_f   scand
309
310         mov_lfsr message_buffer, 1
311         bt_f_if0 buf0, 7
312         bra     msg_copy_exitnone
313         ; some extra bytes to copy
314 ;...
315 msg_copy_loop
316         mov_fw  POSTINC1
317         mov_wf  POSTINC2
318         bra_n   msg_copy_loop
319 ;...
320 msg_copy_exitnone
321         mov_ff  FSR2L, outmsg_end
322         mov_ff  buf0_startval, buf0
323         mov_lfsr outbuf, 2
324
325 reset_detectread
326 ;  FSR1/buf0/message_buffer     any             set to empty
327 ;  unattended*                  any             reset
328 ;  Per-PIC LED                  any             black
329 ;  may be called from High ISR or during init
330         mov_lfsr buf0, 1
331
332         call    led_black
333
334 unattended_timeout equ 100 ; ms
335         set_f   unattendedl
336         ; Fosc = sclock [kHz]
337         ; Fcy = sclock / 4  [kHz]
338         ; program counter advance rate = 2 * sclock / 4  [bytes/ms]
339         ; unattendedh increment rate = pc advance rate / 256
340         ;       = 2 * sclock / (4 * 256)  [counts/ms]
341         ; count needed before show unattended = uah rate * ua timeout
342         ;       = (2 * sclock / (4 * 256)  [counts/ms])
343         ;               * (unattended_timeout [ms])
344         ;       = (2 * sclock / (4 * 256)) * unattended_timeout  [counts]
345         ;       = sclock * unattended_timeout / 512  [counts]
346         ; we count up until overflow, so
347 unattended_init equ 65535 - (sclock * unattended_timeout / 512)
348         mov_lw  unattended_init / 256
349         mov_wf  unattendedu
350         mov_lw  unattended_init & 255
351         mov_wf  unattendedh
352
353         return
354
355 ;----------
356 new_i2c_outmsg
357 ; Called from i2csu_read_begin ISR to check that the whole of
358 ; the previous message was read, and to reset the FSR2 pointer
359 ; to point to the start of outbuf so that we can fill the outbuf.
360         mov_fw  FSR2L           ; W -> byte after the one we last sent
361         mov_lfsr outbuf, 2      ; FSR2 -> outbuf
362         cmp_fw_ifle outmsg_end  ; transmitted the last byte ?
363         return
364         ; no, oops:
365         panic   morse_DQ
366
367 ;----------------------------------------------------------------------
368 ; reversers
369                         ; A     xx 01 xx 03  xx xx xx xx
370                         ; B     xx xx xx xx  xx xx xx xx
371                         ; C     xx xx xx xx  xx 00 xx xx
372                         ; D     xx xx xx xx  xx xx 04 05
373 ;----------             ; E     xx xx xx xx  xx 02 xx xx
374 backgroundloop_reversers_core macro
375         rr_fw   PORTA   ; W     xx xx 01 xx  03 xx xx xx (now)
376         and_wff scana   ; a     xx xx 01 xx  03 xx xx xx (cumulative)
377         mov_fw  PORTD   ; D     xx xx xx xx  xx xx 04 05 (now)
378         and_wff scand   ; d     xx xx xx xx  xx xx 04 05 (cumulative)
379         bt_f_if0 PORTC,2 ;                      00       (now)
380         bc_f    buf0,2  ; buf0  MM zz zz ss  zz 00 zz zz (cumulative)
381         bt_f_if0 PORTE,2 ;                      02       (now)
382         bc_f    buf0,4  ; buf0  MM zz zz 02  zz ss zz zz (cumulative)
383         endm
384 backgroundloop_reversers @
385         backgroundloop_reversers_core
386         backgroundloop_again backgroundloop_reversers
387
388 ;----------             ; buf0  MM zz zz 02  zz 00 zz zz
389 read_begin_calc_buf0_reversers macro
390         mov_fw  scana   ; W     xx xx 01 xx  03 xx xx xx
391         and_lw  0x28    ; W     zz zz 01 zz  03 zz zz zz
392         ior_wff buf0    ; buf0  MM zz 01 02  03 00 zz zz
393
394         mov_fw  scand   ; W     xx xx xx xx  xx xx 04 05
395         and_lw  0x03    ; W     zz zz zz zz  zz zz 04 05
396         ior_wfw buf0    ; W     MM zz 01 02  03 00 04 05
397         endm
398
399 i2csu_read_begin_reversers
400         read_begin_calc_buf0_reversers
401         call    i2cs_read_data
402
403         rcall   new_i2c_outmsg
404
405         bra     i2csu_read_begin_either_tail
406
407 ;======================================================================
408 ; FOR MASTER
409
410 ;----------
411 backgroundloop_master @
412         backgroundloop_reversers_core
413         bra     backgroundloop_master
414
415 ;----------
416 read_detection_head_master @
417         read_begin_calc_buf0_reversers
418         bra_n   read_detection_head_master_badmore
419         set_f   scana
420         set_f   scand
421         mov_ff  buf0_startval, buf0
422         return
423
424 ;-----
425 read_detection_head_master_badmore
426         panic   morse_DM
427
428 ;======================================================================
429   include final.inc