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