chiark / gitweb /
reserve /^ [^ ;]/ for statements inserted for debugging purposes
[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 panicst_ferroerr                equ     4
22 panicst_writeslave              equ     3
23
24 panic_valcount                  res     1
25
26 panic_vars_section udata 0x060 + maxpics ; not available via access bank
27 ; used in panic routine for temporary storage:
28
29 flash_pattern           res     1
30 morse_counter           res     1
31 register_counter        res     1
32 bit_counter             res     1
33
34 panic_address   res     1       ; condensed form of message start addr.
35 panic_morse     res     1       ; # bytes of morse msg in panic readout
36 panic_regs      res     1       ; # registers in panic readout
37
38 t0l_count       res     1
39 t0h_count       res     1
40
41 psave_latc      res     1
42 psave_t         res     1
43 psave_tablat    res     1
44 psave_tblptr    res     3
45 psave_fsr0      res     2
46 psave_fsr1      res     2
47 psave_prod      res     2
48 psave_stkptr    res     1
49
50 stack_depth     equ     31
51 panic_stack     res     stack_depth*3
52
53 ;****************************************************************************
54
55 pan_ code
56
57 ;****************************************************************************
58
59
60 panic_routine
61 ; switch off interrupts and power
62 ; reconfigure timer0 for writing diagnostic msg to the LED
63
64         mov_ff  INTCON, psave_intcon
65         bc_f    INTCON, GIEH   ; disable all interrupts
66
67         mov_ff  BSR, psave_bsr
68         banksel flash_pattern
69
70         mov_ff  LATC, psave_latc
71
72 ; now we have time to save registers etc
73 ; (turning off interrupts is urgent (we might get interrupted while
74 ;  panicing which would be bad because we might forget to panic).
75
76         mov_wf   panic_address
77
78         mov_ff  t, psave_t
79         mov_ff  TABLAT, psave_tablat
80         mov_ff  TBLPTRL, psave_tblptr
81         mov_ff  TBLPTRH, psave_tblptr+1
82         mov_ff  TBLPTRU, psave_tblptr+2
83         mov_ff  FSR0L, psave_fsr0
84         mov_ff  FSR0H, psave_fsr0+1
85         mov_ff  FSR1L, psave_fsr1
86         mov_ff  FSR1H, psave_fsr1+1
87         mov_ff  PRODL, psave_prod
88         mov_ff  PRODH, psave_prod+1
89         mov_ff  STKPTR, psave_stkptr
90
91         mov_lfsr panic_stack + stack_depth*3 - 1, 0
92         mov_lw  stack_depth
93         mov_wf  STKPTR
94 stacksave_loop
95         mov_ff  TOSU, POSTDEC0
96         mov_ff  TOSH, POSTDEC0
97         mov_ff  TOSL, POSTDEC0
98         dec_f_ifnz STKPTR
99         bra     stacksave_loop
100
101         clr_f    STKPTR         ; avoids stack overruns
102         clr_f   panicst
103
104         call    panic_kill_hook
105
106 ; re-initialise timer0 config, etc.
107         call    read_pic_no
108         bra_z   panic_setup_if_master
109 panic_setup_if_slave
110         morse_t0setup sclock, (1<<TMR0ON), t0l_count, t0h_count
111         bra     panic_setup_endif_masterslave
112
113 panic_setup_if_master
114         pin_l   p0_booster_userfault
115         mov_lw  0x0b ; AAARGH
116         bt_f_if1 TXSTA, TXEN
117         call    serial_write_char
118         morse_t0setup mclock, (1<<TMR0ON), t0l_count, t0h_count
119 panic_setup_endif_masterslave
120
121 ; get # bytes of morse msg, # registers in panic readout, message start addr.
122 ; back from condensed message start addr. stored in panic_address
123
124 panic_loop
125         mov_lw  4 ; size of each message's details
126         mul_wf  panic_address
127         mov_ff  PRODL,TBLPTRL           
128         mov_ff  PRODH,WREG
129         add_lw  (morse_messages_start)/256
130         mov_wf  TBLPTRH
131         clr_f   TBLPTRU
132
133         tblrd   *+              ; read 1st byte of error message
134                                 ; (gives # bytes morse, # bytes registers)
135         dw      0xffff ; silicon errata: B4 issue 4
136
137         mov_ff  TABLAT,panic_morse
138         mov_lw  00001111b
139         and_wff panic_morse     ; panic_morse now contains # bytes of morse msgs
140
141         mov_ff  TABLAT,panic_regs
142         mov_lw  01110000b
143         and_wff panic_regs
144         swap_f  panic_regs      ; panic_regs now contains # registers to read
145
146         call    led_black
147         rcall   waiting16
148         rcall   morsemsg        ; transmit morse in red
149         call    led_black
150         rcall   waiting8
151         rcall   waiting4
152         rcall   registermsg     ; transmit contents of registers in 
153                                 ; red(=low) and blue(=high)
154         rcall   waiting16
155         bra     panic_loop
156
157 ;****************************************************************************
158 ; PANIC SUBROUTINES
159
160 morsemsg
161 ; wrapper round morse_readout to flash the per-pic led red for a morse msg
162
163 morse_msg_start
164         clr_f           morse_counter           ; clear loop counter
165
166 morse_loop
167         mov_fw          panic_morse
168         cmp_fw_ifge     morse_counter           ; if loop counter >=panic_morse
169         return                                  ; return to panic
170
171         tblrd           *+
172         mov_ff          TABLAT,flash_pattern
173         rcall           morse_readout
174         inc_f           morse_counter
175         bra             morse_loop
176
177
178 ;--------------------------
179 morse_readout
180
181 ; Flashes the per-pic led and black in a specified pattern.
182 ;
183 ; The pattern is specified as the state for 8 identically-long time
184 ; periods each as long as a morse `dot', encoded into a byte with
185 ; most significant bit first.
186 ;                       On entry                On exit
187 ; W                     any                     undefined
188 ; flash_pattern         flash pattern           preserved
189 ; bit_counter           any                     undefined
190
191         mov_lw          9
192         mov_wf          bit_counter
193         rr_f            flash_pattern
194
195 morse_readout_loop
196         dec_f_ifz       bit_counter             ; done all the bits yet ?
197         return
198         ; No:
199
200         rl_f            flash_pattern           ; top bit goes into N, 
201                                                 ;ie Negative if 1
202         bra_n           morse_readout_if_led_1
203
204 morse_readout_if_led_0
205         call            led_black
206         bra             morse_readout_endif_led
207
208 morse_readout_if_led_1
209         call            led_red
210
211 morse_readout_endif_led
212         rcall           waiting
213         bra             morse_readout_loop
214
215 ;--------------------------
216 ;--------------------------
217 registermsg
218
219 register_msg_start
220         clr_f           register_counter        ; clear loop counter
221
222 register_loop
223         mov_fw          panic_regs
224         cmp_fw_ifge     register_counter        ; if loop counter >=panic_regs
225         return                                  ; return to panic
226
227         tblrd           *+
228
229         mov_fw          TABLAT          ; TABLAT has the 8-bit version
230         mov_wf          FSR0L           ; of the address.  So, 8 bits
231                                         ; go straight into FSR0L.
232
233         mov_lw          0x0f            ; For FSR0H, we see if the
234         mov_fw          FSR0H           ; address XX is >=0x60.
235                                         ; If it is then we meant 0xfXX;
236         mov_lw          0x5f            ; if not then we meant 0x0XX.
237         cmp_fw_ifle     FSR0L           ; (This is just like PIC does
238         clr_f           FSR0H           ; for insns using Access Bank)
239
240         mov_ff          INDF0,flash_pattern
241         rcall           register_readout
242
243         inc_f           register_counter        ;increment loop counter
244
245         rcall           waiting8
246         bra             register_loop
247
248 ;--------------------------
249
250 register_readout
251
252 ; Flashes the per-pic led red(0) and green(1) in a specified pattern.
253 ; (black gap between each bit)
254 ;
255 ; The pattern is specified as the state for 8 identically-long time
256 ; periods each as long as a morse `dot', encoded into a byte with
257 ; most significant bit first.
258 ;                       On entry                On exit
259 ; W                     any                     undefined
260 ; flash_pattern         flash pattern           preserved
261 ; bit_counter           any                     undefined
262
263         clr_f   bit_counter             ; clear loop counter
264         rr_f    flash_pattern
265
266
267 register_readout_loop
268         mov_lw          8
269         cmp_fw_ifge     bit_counter             ; if loop counter >=8 (register 
270                                                 ; length), return
271         return
272
273         mov_lw          4
274         cmp_fw_ifne     bit_counter     ; if loop counter !=4 (nybble length), 
275                                         ; skip insertion of extra black space
276         bra             not_nybble_boundary
277         rcall           waiting4
278
279 not_nybble_boundary
280         rl_f            flash_pattern           ; top bit goes into N flag, 
281                                                 ; ie Negative if 1
282         bra_n           register_readout_if_led_1
283
284 register_readout_if_led_0
285         call            led_red
286         bra             register_readout_endif_led
287
288 register_readout_if_led_1
289         call            led_green
290
291 register_readout_endif_led
292         inc_f           bit_counter       ; increment loop counter
293         rcall           waiting
294         call            led_black
295         rcall           waiting
296         bra             register_readout_loop
297
298
299 ;****************************************************************************
300 ; GENERAL SUBROUTINES
301
302 ;----------------------------------------
303 waiting16       rcall   waiting8
304 waiting8        rcall   waiting4
305 waiting4        rcall   waiting2
306 waiting2        rcall   waiting
307 waiting
308 ; waits for a fixed interval, depending on the configuration of TMR0
309
310         bt_f_if1 idloc1,idloc1_master
311         pin_z   p0_booster_userfault
312
313         bc_f    INTCON,2        ; clear timer0 interrupt bit (p109)
314 ; Interrupt happens on overflow.  So start at 65535-morse_t0cycles:
315         mov_fw  t0h_count
316         mov_wf  TMR0H           ; p107 set high byte of timer0 (buffered,
317                                 ; only actually set when write to tmr0l occurs)
318         mov_fw  t0l_count
319         mov_wf  TMR0L           ; set timer0 low byte - timer now set
320 waiting_loop    ; wait for timer0 interrupt, or some other interrupt
321         bt_f_if1 INTCON,TMR0IF
322         return
323
324         bt_f_if1 idloc1, idloc1_master
325         bra     waiting_master
326         ; slave:
327
328         bt_f_if0 SSPCON1, SSPEN
329         bra     waiting_loop    ; no readouts if i2c is disabled
330         ; slave, i2c enabled:
331
332         bt_f_if1 PIR1, SSPIF
333         call    pan_i2cs_interrupt
334
335         bra     waiting_loop
336
337 ;----------------------------------------
338 ; MASTER'S PANIC SERIAL PORT HANDLING
339
340 ;--------------------
341 waiting_master
342         bt_f_if1 PIR1,RCIF ; host sent us something ?
343         call    panicd_serialrx
344
345         bt_f_if0 SSPCON1, SSPEN
346         bra     waiting_loop
347         ; master, i2c enabled:
348
349         bt_f_if1 PIR1, SSPIF
350         rcall   pan_i2cm_interrupt
351
352         bra     waiting_loop
353
354 ;----------
355 panicst_oerrferr
356         dec_fw  RCREG
357         bra_nz  panicd_serialrx_err_loop
358         ; yay! host ack'd ferr/oerr
359         bc_f    panicst, panicst_ferroerr
360         return ; return from panicd_serialrx
361
362 ;----------
363 panicd_serialrx_err
364         bs_f    panicst, panicst_ferroerr
365         bc_f    RCSTA, RCEN     ; disable       } to clear FERR/OERR
366         mov_fw  RCREG           ; read RCREG    } (see PIC18FXX8 DS p182)
367         bs_f    RCSTA, RCEN     ; reenable      }
368 panicd_serialrx_err_loop
369         bt_f_if0 PIR1, RCIF ; wait for a byte 0x01 to ack the overrun/error
370         bra     panicd_serialrx_err_loop
371 ;...
372 ;----------
373 panicd_serialrx
374         pin_nz  p0_booster_userfault
375         bt_f_if1 RCSTA,FERR
376         bra     panicd_serialrx_err
377         bt_f_if1 RCSTA,OERR
378         bra     panicd_serialrx_err
379         bt_f_if1 panicst, panicst_ferroerr
380         bra     panicst_oerrferr
381
382         mov_fw  RCREG
383 ;...
384 ;****************************************************************************
385 ; MEMORY READOUT
386
387 ;----------
388 pan_i2csu_write_data
389 panicd_process_input_byte
390 ;               W       instruction from host or master
391         tst_w_ifnz
392         bra     write_ifnot_00
393         ; we've received 0x00:
394
395         mov_lfsr 0,1
396         bs_f    panicst, panicst_acked
397         return
398
399 ;----------
400 write_ifnot_00
401         bt_f_if0 panicst, panicst_acked ; well, ignore that !
402         return
403         ; OK, we have an instruction:
404
405         bt_w_if1 7 ; huh?
406         bra     write_if_setbytetowrite
407         bt_w_if1 6
408         bra     panic_crashread_setpointer
409         bt_f_if0 idloc1,idloc1_master
410         return ; all the remaining options are for master only
411         bt_w_if1 5
412         bra     write_if_master_slaveselect
413         bt_w_if1 4
414         bra     write_if_master_masterread
415         bra     write_if_master_slaveread
416         return ; huh ?
417
418 ;----------
419 panic_crashread_setpointer
420 ;  W                    byte from master or host        undefined
421 ;  FSR1*                crashread pointer               updated
422 ;  t, STATUS, PROD*     any                             undefined
423 ;  all others           any                             preserved
424         mov_wf  t
425         mov_lw  1<<6
426         mul_wf  FSR1L
427         mov_ff  PRODH, FSR1H
428         mov_fw  t
429         and_lw  0x3f
430         ior_wfw PRODL
431         mov_wf  FSR1L
432         return
433
434 ;======================================================================
435 ; MASTER READOUT AND MASTER READOUT OF SLAVES
436
437 ;----------
438 write_if_setbytetowrite
439         bt_f_if0 idloc1,idloc1_master
440         return ; for master only
441
442         bc_w    7
443         mov_wf  panic_valcount
444         bs_f    panicst, panicst_writeslave
445         return
446
447 ;----------
448 write_if_master_slaveread
449         mov_wf  panic_valcount
450         bc_f    panicst, panicst_writeslave
451         return
452
453 ;----------
454 write_if_master_slaveselect
455         bc_w    5
456         bt_f_if1 panicst, panicst_writeslave
457         bra     pan_i2cm_write_start
458         bra     pan_i2cm_read_start
459
460 ;----------
461 write_if_master_masterread
462         bc_w    4
463         mov_wf  panic_valcount
464 write_if_master_masterread_loop
465         mov_fw  POSTINC1
466         call    serial_write_char
467         dec_f_ifnz panic_valcount
468         bra     write_if_master_masterread_loop
469         return
470
471 ;----------
472 pan_i2cmu_read_got_byte
473         call    serial_write_char
474         dec_fw_ifnz panic_valcount
475         bra     pan_i2cm_read_another
476         return
477
478 ;----------
479 pan_i2cmu_write_next_byte
480         mov_fw  panic_valcount
481         bs_f    STATUS, Z
482         bt_f_if1 panicst, panicst_writeslave
483         bc_f    STATUS, Z
484         bc_f    panicst, panicst_writeslave
485         return
486
487 ;----------
488 pan_i2cmu_done
489         mov_lw  ' '
490         goto    serial_write_char
491
492 ;======================================================================
493 ; SLAVE I2C
494
495 pan_near_i2csu code
496 ;----------
497 pan_i2csu_write_begin
498         return
499
500 ;----------
501 pan_i2csu_read_begin
502         mov_lw  0x80 ; M0000000
503         bt_f_if0 panicst, panicst_acked
504         goto    i2cs_read_data
505 ;...
506 i2csu_read_panicd_ok
507         mov_fw  POSTINC1
508         goto    i2cs_read_data
509
510 ;----------
511 pan_i2csu_read_another
512         bt_f_if1 panicst, panicst_acked
513         bra     i2csu_read_panicd_ok
514         ; not ok
515         mov_lw  0x0b ; AARGH
516         goto    i2cs_read_data
517
518 near_gots code
519 ;----------
520 got_aargh
521         panic   morse_T
522
523 near_serialrx_table code 0x2100
524 ;----------
525 command_crashed
526 panic_crashread_commanded
527         bs_f    panicst, panicst_acked ; since we were asked to
528         panic   morse_E
529
530 ;***************************************************************************
531         include final.inc