> 0 0100 001 ON Power on
> 0 0100 000 OFF Power off
+ > 00000000 CRASHED Acknowledge panic, go to readout mode
+
+; In crash readout mode:
+;
+; 00000000 MS Select crash readout mode if not already
+; Reset crash readout pointer to 0
+;
+; 1vvvvvvv M Prepare byte 0vvvvvvv for transmission to the slave
+;
+; 0000nnnn M (n>0) prepare to receive nnnn bytes from slave
+; 0001nnnn M (n>0) transmit nnnn bytes of our own from the
+; readout pointer
+;
+; 001sssss M Select slave S^0x10. Then:
+; After 1vvvvvvv
+; Transmit just 0vvvvvvv to slave
+; and then send some some unspecified byte to host
+; After 0000nnnn
+; Receive as nnnn bytes, forwarding each one
+; to the host.
+; After the transaction is complete, 1vvvvvvv
+; or 0000nnnn must be specified again before
+; 001sssss is repeated.
+;
+; 01bbbbbb MS Supply 6 bits for crash readout pointer
+; (crash readout mode only)
+; Effect is FSR << 6; FSR |= bbbbbb
+
From PIC to host:
< 1 001Y SSS 0 SSSSSSS DETECT Train is (Y=1) or is not (Y=0) at S
; MM indicates that further extra message bytes follow;
; it is clear iff this is the last extra message byte.
; XX are the lower 7 bits of a POLARISED or POINTED
-; message (see README.protocol).
+; or AAARGH message (see README.protocol).
; Master may also write to slave. Every written byte is independent:
;
; 11RRRRRR Set reverse to RRRRRR, see reverse.asm
; 100PPPPP Fire point PPPPP
+;
+; 00000000 Acknowlege that slave has crashed, and
+; switch into crash readout mode
;======================================================================
; variables and memory organisation
;----------
i2csu_read_begin
; called from High ISR, see i2clib.inc
+ bt_f_if1 picno,picno_panicd
+ bra i2csu_read_begin_panicd
bt_f_if1 idloc1,idloc1_boarddet
bra i2csu_read_begin_detectors
bra i2csu_read_begin_reversers
;----------
i2csu_read_another
; called from High ISR, see i2clib.inc
+ bt_f_if1 picno,picno_panicd
+ bra i2csu_read_another_panicd
mov_fw POSTINC2
call i2cs_read_data
mov_fw outmsg_end
code
+;----------
+i2cpanic macro morse_addr
+; Like panic but turns off the I2C controller
+ bc_f SSPCON1, SSPEN
+ panic morse_addr
+ endm
+
;----------
slave2addr
; computes slave address in form suitable for use in i2c controller
;----------
improper_read_done_data
- panic morse_SD
+ i2cpanic morse_SD
;======================================================================
; MASTER
bra m_event_done_reading
m_event_bad
- panic morse_SM
+ i2cpanic morse_SM
;========================================
; MASTER - STARTING, ADDRESSING, STOPPING
;----------
m_bad_address_ack
- panic morse_SK
+ i2cpanic morse_SK
;----------
m_improper_slave
; slave slave number
- panic morse_SN
+ i2cpanic morse_SN
;========================================
; MASTER - WRITING
;----------
m_improper_write_start
- panic morse_SW
+ i2cpanic morse_SW
;----------
m_improper_write_finish
- panic morse_SF
+ i2cpanic morse_SF
;========================================
; MASTER - READING
m_read_start_busy
bt_f_if1 st, st_awaiting
bra m_read_different
- panic morse_SR
+ i2cpanic morse_SR
;----------
m_read_different
;----------
m_improper_read_another
- panic morse_SA
+ i2cpanic morse_SA
;======================================================================
; SLAVE
chkvals_start SSPSTAT
chkvals_addrrecv 0 ; 23cy to 1st insn of addrrecvread
s_event_bad
- panic morse_SS ; slave, interrupt, controller in bad state
+ i2cpanic morse_SS ; slave, interrupt, controller in bad state
s_event_bad_intr
- panic morse_IH ; unknown high-priority interrupt
+ i2cpanic morse_IH ; unknown high-priority interrupt
;========================================
; SLAVE - READING
;----------
s_event_idle_addrrecvread
bs_f st, st_awaiting
- call QQ_i2csu_read_begin ; 26cy until 1st insn of read_begin
+ call i2csu_read_begin ; 26cy until 1st insn of read_begin
retfie_r
;----------
mov_fw SSPSTAT
xor_lw 0xac ; D,!P, S,R,!BF
bra_nz s_event_reading_not_another
- call QQ_i2csu_read_another
+ call i2csu_read_another
; 24cy until 1st insn of i2csu_read_another
s_event_reading_datanack
retfie_r
;---------------------------------------------------------------------------
; reserved access bank locations
- udata_acs
-
+ udata_acs
+
+psave_w res 1
+psave_t res 1
+psave_intcon res 1
+psave_bsr res 1
+psave_latc res 1
+psave_tablat res 1
+psave_tblptr res 3
+psave_fsr0 res 2
+psave_fsr1 res 2
+psave_prod res 2
+
+panicst res 1
+panicst_acked equ 7
+
+panic_vars_section udata 0x060 ; not available via access bank
+panic_vars
; used in panic routine for temporary storage:
flash_pattern res 1
; switch off interrupts and power
; reconfigure timer0 for writing diagnostic msg to the LED
+ mov_ff INTCON, psave_intcon
clr_f INTCON ; disable all interrupts EVER
- bc_f PORTC,1 ; switch off booster
+
+ mov_ff BSR, psave_bsr
+ banksel panic_vars
+
+ mov_ff LATC, psave_latc
+
+ mov_wf psave_w
; now we have time to copy the panic message address out of WREG
; (turning off interrupts is urgent (we might get interrupted while
mov_wf panic_address
clr_f STKPTR ; avoids stack overruns
+ mov_ff t, psave_t
+ mov_ff TABLAT, psave_tablat
+ mov_ff TBLPTRL, psave_tblptr
+ mov_ff TBLPTRH, psave_tblptr+1
+ mov_ff TBLPTRU, psave_tblptr+2
+ mov_ff FSR0L, psave_fsr0
+ mov_ff FSR0H, psave_fsr0+1
+ mov_ff FSR1L, psave_fsr1
+ mov_ff FSR1H, psave_fsr1+1
+ mov_ff PRODL, psave_prod
+ mov_ff PRODH, psave_prod+1
+
+ clr_f panicst
+
call panic_kill_hook
; re-initialise timer0 config
; only actually set when write to tmr0l occurs)
mov_fw t0l_count
mov_wf TMR0L ; set timer0 low byte - timer now set
-waiting_loop
- bt_f_if0 INTCON,TMR0IF
- bra waiting_loop ; wait for timer0 interrupt
- return
+waiting_loop ; wait for timer0 interrupt, or some other interrupt
+ bt_f_if1 INTCON,TMR0IF
+ return
+
+ bt_f_if0 SSPCON1, SSPEN
+ bra waiting_loop ; no readouts if i2c is disabled
+
+ bt_f_if1 idloc1, idloc1_master
+ bra waiting_loop ; no readouts on master yet
+
+ call i2cs_interrupt ; check for i2c interrupt
+
+ bra waiting_loop
;****************************************************************************
+; MEMORY READOUT
+
+;----------
+i2csu_write_panicd
+panicd_process_input_byte
+; W instruction from host or master
+ tst_w_ifnz
+ bra write_ifnot_00
+ ; we've received 0x00:
+
+ mov_lfsr 0,1
+ bs_f panicst, panicst_acked
+ return
+
+;----------
+write_ifnot_00
+ bt_f_if0 panicst, panicst_acked ; well, ignore that !
+ return
+ ; OK, we have an instruction:
+
+ bt_w_if1 7 ; huh?
+ return
+ bt_w_if1 6
+ bra write_if_setpointer
+ bt_f_if0 idloc1,idloc1_master
+ return ; all the remaining options are for master only
+;nyi bt_w_if1 5
+;nyi bra write_if_selectslave
+;nyi bt_w_if1 4
+;nyi bra write_if_readout
+ return ; huh ?
+
+;----------
+write_if_setpointer
+ mov_wf t
+ mov_lw 1<<6
+ mul_wf FSR1L
+ mov_ff PRODH, FSR1H
+ mov_fw t
+ and_lw 0x3f
+ ior_wfw PRODL
+ mov_wf FSR1L
+ return
+;----------
+i2csu_read_begin_panicd
+ mov_lw 0x80 ; M0000000
+ bt_f_if0 panicst, panicst_acked
+ goto i2cs_read_data
+;...
+i2csu_read_panicd_ok
+ mov_fw POSTINC1
+ goto i2cs_read_data
+
+;----------
+i2csu_read_another_panicd
+ bt_f_if1 panicst, panicst_acked
+ bra i2csu_read_panicd_ok
+ ; not ok
+ mov_lw 0x0b ; AARGH
+ goto i2cs_read_data
+
+;***************************************************************************
include final.inc
extern panic_routine
extern panic_kill_hook
+ extern i2csu_write_panicd
+ extern i2csu_read_begin_panicd
+ extern i2csu_read_another_panicd
panic macro message
movlw (message - morse_messages_start)/4
- goto panic_routine
+ goto panic_routine
endm
;--------------------
;----------
point_initing_bad_point
- panic morse_PF
- mov_lw 0x11
- mov_wf POSTINC0
- mov_lw 0x22
- mov_wf POSTINC0
- mov_lw 0x33
- mov_wf POSTINC0
-
- mov_ff t, POSTINC0
-
- mov_lw 0x44
- mov_wf POSTINC0
-
- mov_ff TBLPTRU, POSTINC0
- mov_ff TBLPTRH, POSTINC0
- mov_ff TBLPTRL, POSTINC0
-
- mov_lw 0x55
- mov_wf POSTINC0
-
- return;qq
-
-
-
panic morse_PF
;----------
;----------
i2csu_write_begin
i2csu_write_another
+ bt_f_if1 picno,picno_panicd
+ goto i2csu_write_panicd
goto led_black
;----------
; if first byte of buffer _is_ negative:
; i2cm_read_start (buffer empty)
;
-; < 0x20 panic, showing character code
+; 0x00 do not send this
+;
+; 0x80-ff make buffer consisting of only that byte
+; (ie, clear top bit, store at start of buffer,
+; set buffer pointer to next byte and clear that one)
+;
+; 0x01-0f store value in readnext counter
+;
+; 0x10-1f panic, showing character code
;
-; , i2cm_read_another
-; . i2cm_read_done
+; , i2cm_read_another } if readnext_counter<7> is clear
+; . i2cm_read_done } then these are not called;
+; } instead, we count down automatically
;
; SPC set buffer pointer to start, set that byte to 0xff
; 0 set buffer pointer to start, clear that byte
; $ toggle hex mode for reading
;
; Output characters:
-; SPC i2cmu_done
+; SPC i2cmu_done (only if readnext_counter<7> is set;
+; if it is clear we store 0xff in
+; readnext_counter)
; other i2cmu_read_got_byte
;
; On slave PIC:
udata_acs
-ch res 1
-mode res 1
-mode_readhex equ 0
+ch res 1
+mode res 1
+mode_readhex equ 0
+readnext_counter res 1
delay_countfast res 1
delay_countmedium res 1
rcall m_buffer_reset
set_f INDF1
+ set_f readnext_counter
+
mov_lw '|'
rcall serial_write_char
mov_lw (1<<GIEH) | (1<<GIEL)
; W character read any
mov_wf ch
+ bt_f_if1 ch, 7
+ bra m_ch_setonemsg
+
+ mov_lw ~0x0f
+ and_wfw ch
+ bra_z m_ch_setreadnext
+
mov_lw ~0x1f
and_wfw ch
bra_z m_ch_bad
clr_f FSR0H ; prevent crashes due to wrapping
bra m_buffer_fix_fsr0h
+;----------
+m_ch_setonemsg
+ mov_lfsr 0x200,0
+ mov_fw ch
+ and_lw 0x7f
+ mov_fw POSTINC0
+ clr_f INDF0
+ return
+
;----------
m_ch_bad
panic morse_X
+;----------
+m_ch_setreadnext
+ mov_ff ch, readnext_counter
+ return
+
;----------
m_ch_comma
goto i2cm_read_another
;----------------------------------------
i2cmu_done
mov_lw ' '
+ bt_f_if1 readnext_counter, 7
+ bra serial_write_char
+ set_f readnext_counter
+ return
+
+;----------
i2cmu_read_got_byte
+ rcall read_got_print
+
+ bt_f_if1 readnext_counter, 7
+ return
+ ; ok, so we're in automatic mode:
+ dec_f_ifnz readnext_counter
+ bra i2cm_read_another
+ bra i2cm_read_done
+
+;----------
+read_got_print
bt_f_if0 mode,mode_readhex
bra serial_write_char
bra serial_write_hex
+;----------
+i2cmu_done_ifreadnextauto
+ set_f readnext_counter
+ return
+
;----------
i2cmu_write_next_byte
mov_fw POSTINC2
udata_acs
picno res 1 ; from first idlocs byte
+picno_panicd equ 7 ; this bit set if we panic
+
idloc1 res 1 ; from 2nd idlocs byte; bit 7 is master:
idloc1_master equ 7
idloc1_boarddet equ 6
+
t res 1 ; general temporary
outmsg_end res 1 ; first empty byte in outbuf