1 ;======================================================================
4 ; This file implements panic_routine, which is called by the
5 ; `panic' macro in panic.inc. See panic.inc for the functionality
10 ;---------------------------------------------------------------------------
11 ; reserved access bank locations
15 ; used in panic routine for temporary storage:
19 register_counter res 1
22 panic_address res 1 ; condensed form of message start addr.
23 panic_morse res 1 ; # bytes of morse msg in panic readout
24 panic_regs res 1 ; # registers in panic readout
27 ;****************************************************************************
31 ;****************************************************************************
34 ; switch off interrupts and power
35 ; reconfigure timer0 for writing diagnostic msg to the LED
37 clr_f INTCON ; disable all interrupts EVER
38 bc_f PORTC,1 ; switch off booster
40 ; now we have time to copy the panic message address out of WREG
41 ; (turning off interrupts is urgent (we might get interrupted while
42 ; panicing which would be bad because we might forget to panic).
45 clr_f STKPTR ; avoids stack overruns
47 ; re-initialise timer0 config
48 mov_lw (1<<TMR0ON) | 011b ; Enable, 16-bit, timer, prescaler 1:16
49 mov_wf T0CON ; => PSout is 312.5kHz or 3.2us per period (DS p108)
50 ; We want to wait 66ms (morse at 18wpm according to the PARIS standard
51 ; is a unit time of 66ms), or 20,833 PSout cycles:
52 waiting_t0cycles equ 20833 ; see by `waiting', below
54 ; get # bytes of morse msg, # registers in panic readout, message start addr.
55 ; back from condensed message start addr. stored in panic_address
58 mov_lw 4 ; size of each message's details
62 add_lw (morse_messages_start)/256
66 tblrd *+ ; read 1st byte of error message
67 ; (gives # bytes morse, # bytes registers)
68 dw 0xffff ; silicon errata: B4 issue 4
70 mov_ff TABLAT,panic_morse
72 and_wff panic_morse ; panic_morse now contains # bytes of morse msgs
74 mov_ff TABLAT,panic_regs
77 swap_f panic_regs ; panic_regs now contains # registers to read
81 call morsemsg ; transmit morse in red
85 call registermsg ; transmit contents of registers in
86 ; red(=low) and blue(=high)
90 ;****************************************************************************
94 ; wrapper round morse_readout to flash the per-pic led red for a morse msg
97 clr_f morse_counter ; clear loop counter
101 cmp_fw_ifge morse_counter ; if loop counter >=panic_morse
102 return ; return to panic
105 mov_ff TABLAT,flash_pattern
111 ;--------------------------
114 ; Flashes the per-pic led and black in a specified pattern.
116 ; The pattern is specified as the state for 8 identically-long time
117 ; periods each as long as a morse `dot', encoded into a byte with
118 ; most significant bit first.
121 ; flash_pattern flash pattern preserved
122 ; bit_counter any undefined
129 dec_f_ifz bit_counter ; done all the bits yet ?
133 rl_f flash_pattern ; top bit goes into N,
135 bra_n morse_readout_if_led_1
137 morse_readout_if_led_0
139 bra morse_readout_endif_led
141 morse_readout_if_led_1
144 morse_readout_endif_led
146 bra morse_readout_loop
148 ;--------------------------
149 ;--------------------------
153 clr_f register_counter ; clear loop counter
157 cmp_fw_ifge register_counter ; if loop counter >=panic_regs
158 return ; return to panic
162 mov_fw TABLAT ; TABLAT has the 8-bit version
163 mov_wf FSR0L ; of the address. So, 8 bits
164 ; go straight into FSR0L.
166 mov_lw 0x0f ; For FSR0H, we see if the
167 mov_fw FSR0H ; address XX is >=0x60.
168 ; If it is then we meant 0xfXX;
169 mov_lw 0x5f ; if not then we meant 0x0XX.
170 cmp_fw_ifle FSR0L ; (This is just like PIC does
171 clr_f FSR0H ; for insns using Access Bank)
173 mov_ff INDF0,flash_pattern
174 call register_readout
176 inc_f register_counter ;increment loop counter
181 ;--------------------------
185 ; Flashes the per-pic led red(0) and green(1) in a specified pattern.
186 ; (black gap between each bit)
188 ; The pattern is specified as the state for 8 identically-long time
189 ; periods each as long as a morse `dot', encoded into a byte with
190 ; most significant bit first.
193 ; flash_pattern flash pattern preserved
194 ; bit_counter any undefined
196 clr_f bit_counter ; clear loop counter
200 register_readout_loop
202 cmp_fw_ifge bit_counter ; if loop counter >=8 (register
207 cmp_fw_ifne bit_counter ; if loop counter !=4 (nybble length),
208 ; skip insertion of extra black space
209 goto not_nybble_boundary
213 rl_f flash_pattern ; top bit goes into N flag,
215 bra_n register_readout_if_led_1
217 register_readout_if_led_0
219 bra register_readout_endif_led
221 register_readout_if_led_1
224 register_readout_endif_led
225 inc_f bit_counter ; increment loop counter
229 bra register_readout_loop
232 ;****************************************************************************
233 ; GENERAL SUBROUTINES
235 ;----------------------------------------
236 waiting16 rcall waiting8
237 waiting8 rcall waiting4
238 waiting4 rcall waiting2
239 waiting2 rcall waiting
241 ; waits for a fixed interval, depending on the configuration of TMR0
243 bc_f INTCON,2 ; clear timer0 interrupt bit (p109)
244 ; Interrupt happens on overflow. So start at 65535-waiting_t0cycles:
245 mov_lw (65535-waiting_t0cycles) / 256
246 mov_wf TMR0H ; p107 set high byte of timer0 (buffered,
247 ; only actually set when write to tmr0l occurs)
248 mov_lw (65535-waiting_t0cycles) & 0xff
249 mov_wf TMR0L ; set timer0 low byte - timer now set
251 bt_f_if0 INTCON,TMR0IF
252 bra waiting_loop ; wait for timer0 interrupt
256 ;****************************************************************************