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