chiark / gitweb /
use pan_near_i2csu section
[trains.git] / detpic / panic.asm
1 ;======================================================================
2 ; panic.asm
3 ;
4 ; This file implements panic_routine, which is called by the
5 ; `panic' macro in panic.inc.  See panic.inc for the functionality
6 ; of `panic'.
7
8         include common.inc
9
10 ;---------------------------------------------------------------------------
11 ; reserved access bank locations
12
13  udata_acs
14
15 psave_intcon    res     1
16 psave_bsr       res     1
17
18 panicst                         res     1
19 panicst_restart_i2c             equ     7
20 panicst_acked                   equ     5
21
22 panic_vars_section udata 0x060 + maxpics ; not available via access bank
23 ; used in panic routine for temporary storage:
24
25 flash_pattern           res     1
26 morse_counter           res     1
27 register_counter        res     1
28 bit_counter             res     1
29
30 panic_address   res     1       ; condensed form of message start addr.
31 panic_morse     res     1       ; # bytes of morse msg in panic readout
32 panic_regs      res     1       ; # registers in panic readout
33
34 t0l_count       res     1
35 t0h_count       res     1
36
37 psave_latc      res     1
38 psave_t         res     1
39 psave_tablat    res     1
40 psave_tblptr    res     3
41 psave_fsr0      res     2
42 psave_fsr1      res     2
43 psave_prod      res     2
44 psave_stkptr    res     1
45
46 stack_depth     equ     31
47 panic_stack     res     stack_depth*3
48
49 ;****************************************************************************
50
51         code
52
53 ;****************************************************************************
54
55
56 panic_routine
57 ; switch off interrupts and power
58 ; reconfigure timer0 for writing diagnostic msg to the LED
59
60         mov_ff  INTCON, psave_intcon
61         bc_f    INTCON, GIEH   ; disable all interrupts
62
63         mov_ff  BSR, psave_bsr
64         banksel flash_pattern
65
66         mov_ff  LATC, psave_latc
67
68 ; now we have time to save registers etc
69 ; (turning off interrupts is urgent (we might get interrupted while
70 ;  panicing which would be bad because we might forget to panic).
71
72         mov_wf   panic_address
73
74         mov_ff  t, psave_t
75         mov_ff  TABLAT, psave_tablat
76         mov_ff  TBLPTRL, psave_tblptr
77         mov_ff  TBLPTRH, psave_tblptr+1
78         mov_ff  TBLPTRU, psave_tblptr+2
79         mov_ff  FSR0L, psave_fsr0
80         mov_ff  FSR0H, psave_fsr0+1
81         mov_ff  FSR1L, psave_fsr1
82         mov_ff  FSR1H, psave_fsr1+1
83         mov_ff  PRODL, psave_prod
84         mov_ff  PRODH, psave_prod+1
85         mov_ff  STKPTR, psave_stkptr
86
87         mov_lfsr panic_stack + stack_depth*3 - 1, 0
88         mov_lw  stack_depth
89         mov_wf  STKPTR
90 stacksave_loop
91         mov_ff  TOSU, POSTDEC0
92         mov_ff  TOSH, POSTDEC0
93         mov_ff  TOSL, POSTDEC0
94         dec_f_ifnz STKPTR
95         bra     stacksave_loop
96
97         clr_f    STKPTR         ; avoids stack overruns
98         clr_f   panicst
99
100         call    panic_kill_hook
101
102 ; re-initialise timer0 config
103         call    read_pic_no
104         bra_z   panic_setup_if_master
105 panic_setup_if_slave
106         morse_t0setup sclock, (1<<TMR0ON), t0l_count, t0h_count
107         bra     panic_setup_endif_masterslave
108 panic_setup_if_master
109         morse_t0setup mclock, (1<<TMR0ON), t0l_count, t0h_count
110 panic_setup_endif_masterslave
111
112 ; get # bytes of morse msg, # registers in panic readout, message start addr.
113 ; back from condensed message start addr. stored in panic_address
114
115 panic_loop
116         mov_lw  4 ; size of each message's details
117         mul_wf  panic_address
118         mov_ff  PRODL,TBLPTRL           
119         mov_ff  PRODH,WREG
120         add_lw  (morse_messages_start)/256
121         mov_wf  TBLPTRH
122         clr_f   TBLPTRU
123
124         tblrd   *+              ; read 1st byte of error message
125                                 ; (gives # bytes morse, # bytes registers)
126         dw      0xffff ; silicon errata: B4 issue 4
127
128         mov_ff  TABLAT,panic_morse
129         mov_lw  00001111b
130         and_wff panic_morse     ; panic_morse now contains # bytes of morse msgs
131
132         mov_ff  TABLAT,panic_regs
133         mov_lw  01110000b
134         and_wff panic_regs
135         swap_f  panic_regs      ; panic_regs now contains # registers to read
136
137         call    led_black
138         rcall   waiting16
139         rcall   morsemsg        ; transmit morse in red
140         call    led_black
141         rcall   waiting8
142         rcall   waiting4
143         rcall   registermsg     ; transmit contents of registers in 
144                                 ; red(=low) and blue(=high)
145         rcall   waiting16
146         bra     panic_loop
147
148 ;****************************************************************************
149 ; PANIC SUBROUTINES
150
151 morsemsg
152 ; wrapper round morse_readout to flash the per-pic led red for a morse msg
153
154 morse_msg_start
155         clr_f           morse_counter           ; clear loop counter
156
157 morse_loop
158         mov_fw          panic_morse
159         cmp_fw_ifge     morse_counter           ; if loop counter >=panic_morse
160         return                                  ; return to panic
161
162         tblrd           *+
163         mov_ff          TABLAT,flash_pattern
164         rcall           morse_readout
165         inc_f           morse_counter
166         bra             morse_loop
167
168
169 ;--------------------------
170 morse_readout
171
172 ; Flashes the per-pic led and black in a specified pattern.
173 ;
174 ; The pattern is specified as the state for 8 identically-long time
175 ; periods each as long as a morse `dot', encoded into a byte with
176 ; most significant bit first.
177 ;                       On entry                On exit
178 ; W                     any                     undefined
179 ; flash_pattern         flash pattern           preserved
180 ; bit_counter           any                     undefined
181
182         mov_lw          9
183         mov_wf          bit_counter
184         rr_f            flash_pattern
185
186 morse_readout_loop
187         dec_f_ifz       bit_counter             ; done all the bits yet ?
188         return
189         ; No:
190
191         rl_f            flash_pattern           ; top bit goes into N, 
192                                                 ;ie Negative if 1
193         bra_n           morse_readout_if_led_1
194
195 morse_readout_if_led_0
196         call            led_black
197         bra             morse_readout_endif_led
198
199 morse_readout_if_led_1
200         call            led_red
201
202 morse_readout_endif_led
203         rcall           waiting
204         bra             morse_readout_loop
205
206 ;--------------------------
207 ;--------------------------
208 registermsg
209
210 register_msg_start
211         clr_f           register_counter        ; clear loop counter
212
213 register_loop
214         mov_fw          panic_regs
215         cmp_fw_ifge     register_counter        ; if loop counter >=panic_regs
216         return                                  ; return to panic
217
218         tblrd           *+
219
220         mov_fw          TABLAT          ; TABLAT has the 8-bit version
221         mov_wf          FSR0L           ; of the address.  So, 8 bits
222                                         ; go straight into FSR0L.
223
224         mov_lw          0x0f            ; For FSR0H, we see if the
225         mov_fw          FSR0H           ; address XX is >=0x60.
226                                         ; If it is then we meant 0xfXX;
227         mov_lw          0x5f            ; if not then we meant 0x0XX.
228         cmp_fw_ifle     FSR0L           ; (This is just like PIC does
229         clr_f           FSR0H           ; for insns using Access Bank)
230
231         mov_ff          INDF0,flash_pattern
232         rcall           register_readout
233
234         inc_f           register_counter        ;increment loop counter
235
236         rcall           waiting8
237         bra             register_loop
238
239 ;--------------------------
240
241 register_readout
242
243 ; Flashes the per-pic led red(0) and green(1) in a specified pattern.
244 ; (black gap between each bit)
245 ;
246 ; The pattern is specified as the state for 8 identically-long time
247 ; periods each as long as a morse `dot', encoded into a byte with
248 ; most significant bit first.
249 ;                       On entry                On exit
250 ; W                     any                     undefined
251 ; flash_pattern         flash pattern           preserved
252 ; bit_counter           any                     undefined
253
254         clr_f   bit_counter             ; clear loop counter
255         rr_f    flash_pattern
256
257
258 register_readout_loop
259         mov_lw          8
260         cmp_fw_ifge     bit_counter             ; if loop counter >=8 (register 
261                                                 ; length), return
262         return
263
264         mov_lw          4
265         cmp_fw_ifne     bit_counter     ; if loop counter !=4 (nybble length), 
266                                         ; skip insertion of extra black space
267         bra             not_nybble_boundary
268         rcall           waiting4
269
270 not_nybble_boundary
271         rl_f            flash_pattern           ; top bit goes into N flag, 
272                                                 ; ie Negative if 1
273         bra_n           register_readout_if_led_1
274
275 register_readout_if_led_0
276         call            led_red
277         bra             register_readout_endif_led
278
279 register_readout_if_led_1
280         call            led_green
281
282 register_readout_endif_led
283         inc_f           bit_counter       ; increment loop counter
284         rcall           waiting
285         call            led_black
286         rcall           waiting
287         bra             register_readout_loop
288
289
290 ;****************************************************************************
291 ; GENERAL SUBROUTINES
292
293 ;----------------------------------------
294 waiting16       rcall   waiting8
295 waiting8        rcall   waiting4
296 waiting4        rcall   waiting2
297 waiting2        rcall   waiting
298 waiting
299 ; waits for a fixed interval, depending on the configuration of TMR0
300
301         bc_f    INTCON,2        ; clear timer0 interrupt bit (p109)
302 ; Interrupt happens on overflow.  So start at 65535-morse_t0cycles:
303         mov_fw  t0h_count
304         mov_wf  TMR0H           ; p107 set high byte of timer0 (buffered,
305                                 ; only actually set when write to tmr0l occurs)
306         mov_fw  t0l_count
307         mov_wf  TMR0L           ; set timer0 low byte - timer now set
308 waiting_loop    ; wait for timer0 interrupt, or some other interrupt
309         bt_f_if1 INTCON,TMR0IF
310         bra     waiting_done
311
312         bt_f_if0 SSPCON1, SSPEN
313         bra     waiting_loop    ; no readouts if i2c is disabled
314
315         bt_f_if1 idloc1, idloc1_master
316         bra     waiting_loop    ; no readouts on master yet
317
318         bt_f_if1 PIR1, SSPIF
319         call    i2cs_interrupt
320
321         bra     waiting_loop
322
323 ;----------
324 waiting_done
325 ;x      bt_f_if0 panicst, panicst_restart_i2c
326         return
327         bc_f    panicst, panicst_restart_i2c
328         mov_lw  picno
329         and_lw  0x7f
330         bra_z   waiting_done_if_master
331  call i2cs_init
332 lgl
333  call led_green
334  bra lgl
335         goto    i2cs_init
336
337 waiting_done_if_master
338         return
339
340 ;****************************************************************************
341 ; MEMORY READOUT
342
343 ;----------
344 pan_i2csu_write_data
345 panicd_process_input_byte
346 ;               W       instruction from host or master
347         tst_w_ifnz
348         bra     write_ifnot_00
349         ; we've received 0x00:
350
351         mov_lfsr 0,1
352         bs_f    panicst, panicst_acked
353         return
354
355 ;----------
356 write_ifnot_00
357         bt_f_if0 panicst, panicst_acked ; well, ignore that !
358         return
359         ; OK, we have an instruction:
360
361         bt_w_if1 7 ; huh?
362         return
363         bt_w_if1 6
364         bra     panic_crashread_setpointer
365         bt_f_if0 idloc1,idloc1_master
366         return ; all the remaining options are for master only
367 ;nyi    bt_w_if1 5
368 ;nyi    bra     write_if_selectslave
369 ;nyi    bt_w_if1 4
370 ;nyi    bra     write_if_readout
371         return ; huh ?
372
373 ;----------
374 panic_crashread_setpointer
375 ;  W                    byte from master or host        undefined
376 ;  FSR1*                crashread pointer               updated
377 ;  t, STATUS, PROD*     any                             undefined
378 ;  all others           any                             preserved
379         mov_wf  t
380         mov_lw  1<<6
381         mul_wf  FSR1L
382         mov_ff  PRODH, FSR1H
383         mov_fw  t
384         and_lw  0x3f
385         ior_wfw PRODL
386         mov_wf  FSR1L
387         return
388
389 ;----------
390 panic_crashread_commanded
391         bs_f    panicst, panicst_acked ; since we were asked to
392         panic   morse_E
393
394 ;----------
395 pan_i2cmu_read_got_byte
396 pan_i2cmu_write_next_byte
397 pan_i2cmu_done
398         i2cpanic morse_USP
399
400 pan_near_i2csu code
401 ;----------
402 pan_i2csu_write_begin
403         return
404
405 ;----------
406 pan_i2csu_read_begin
407         mov_lw  0x80 ; M0000000
408         bt_f_if0 panicst, panicst_acked
409         goto    i2cs_read_data
410 ;...
411 i2csu_read_panicd_ok
412         mov_fw  POSTINC1
413         goto    i2cs_read_data
414
415 ;----------
416 pan_i2csu_read_another
417         bt_f_if1 panicst, panicst_acked
418         bra     i2csu_read_panicd_ok
419         ; not ok
420         mov_lw  0x0b ; AARGH
421         goto    i2cs_read_data
422
423 near_gots code
424 ;----------
425 got_aargh
426         panic   morse_T
427
428 ;***************************************************************************
429         include final.inc