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