sspstat res 1
sspcon1 res 1
-sspcon2 res 1
+sspcon2 res 1 ; master only
+slave res 1 ; master only
st res 1 ; bitmask, bit set in visible states:
; master slave
st_reading equ 0 ; Reading-* Transmitting
st_writing equ 1 ; Writing-* [Idle-going-]Receiving
-st_subsequent equ 2 ; Receiving
-st_working equ 3 ; Writing-*,Reading-Busy,Stopping
-st_starting equ 4 ; Writing-Setup,Reading-Busy
+st_subsequent equ 2 ; Writing? Receiving
+;st_working equ 3 ; Writing-*,Reading-Busy,Stopping
+st_starting equ 4 ; Writing-Setup?,Reading-Busy?
+st_addressing equ 4 ; Writing-Setup?,Reading-Busy?
+ ; ...? means not always set in that state
code
rlc_w
return
-;----------
-check_wcolsspov
- mov_fw SSPCON1
- mov_wf ssp
- and_lw 0xc0 ; WCOL,SSPOV
- bra_z intr_wcolsspov
- return
-
-;----------
-intr_wcolsspov
- panic morse_SV
-
;======================================================================
; MASTER
bra init_enable
;----------
-i2cm_write_start
-; At call On return
-; State Idle Writing-Setup
-; W slave number any
- tst_f_ifnz st
- bra m_bad_write_start
- bs_f st, st_writing
-m_start
- bs_f st, st_starting
- bs_f SSPCON2, SEN
+i2cm_interrupt
+ bt_f_if0 PIR1, SSPIF
return
+ ; We have an interrupt:
-;----------
-m_bad_write_start
- panic morse_SPW
+ mov_ff SSPSTAT, sspstat
+ mov_ff SSPCON1, sspcon1
+ mov_ff SSPCON2, sspcon2
-;----------
-i2cm_interrupt
- ; Do we have a doomy clash ?
- bsr check_wcolsspov
+ bt_f_if1 sspcon1, WCOL
+ bra_z m_event_bad
+ bt_f_if1 sspcon1, SSPOV
+ bra_z m_event_bad
; No ? Well, then the I2C should be idle now:
- mov_fw SSPCON2
- mov_wf ssp
+ mov_fw sspcon2
and_lw ~0x60 ; ACKSTAT,ACKDT
- bra_nz m_bad_sspcon2
- ; OK, what's happening;
+ bra_nz m_event_bad
+ ; OK...
- bt_f_if0 PIR1, SSPIF
- return
- ; We have an interrupt:
+ bt_f_if1 sspstat, R_W
+ bra_nz m_event_bad
bt_f_if1 st, st_starting
- bra m_event_starting
+ bra m_event_done_starting
; not just done SEN
- fixme
+ bt_f_if1 st, st_addressing
+ bra m_event_done_addressing
-;----------
-m_bad_sspcon2
+m_event_bad
panic morse_SM
+;----------
+m_event_done_starting
+ mov_fw slave
+ bsr slave2addr
+
+ bt_f_if1 st_reading
+ bs_w 0 ; address bottom bit means read
+
+ mov_wf SSPBUF
+ bc_f st, st_starting
+ bs_f st, st_addressing
+ return
;----------
-m_event_starting
- mov_lw 0x88
- bsr m_check_sspstat
+m_event_done_addressing
+ bt_f_if1 sspcon2, ACKSTAT
+ bra m_bad_address_ack
+ ; OK, we got ack.
+ bc_f st, st_addressing
+ bt_f_if1 st, st_reading
+ bra m_event_done_addressing_read
+ bra m_event_done_addressing_write
+
+;----------
+m_bad_address_ack
+ panic morse_SK
-m_check_sspstat
-; W expected bit values any
-; Panics if (SSPSTAT ^ W) & mask != 0
- mov_ff SSPSTAT, ssp
-
+
+ mov_fw slave
+ bsr slave2addr
+
+ bt_f_if1 st_reading
+ bs_w 0 ; address bottom bit means read
+
+ mov_wf SSPBUF
+ bc_f st, st_starting
+ bs_f st, st_addressing
+ return
+
+;----------
+i2cm_write_start
+; At call On return
+; State Idle Writing-Setup
+; W slave number any
+ tst_f_ifnz st
+ bra m_improper_write_start
+ bs_f st, st_writing
+m_start
+ mov_wf slave
+ and_lw 31
+ bra_nz m_improper_slave
+ bs_f st, st_starting
+ bs_f st, st_working
+ bs_f SSPCON2, SEN
+ return
+
+;----------
+m_event_done_writing
+ check for ack ? check this when we bra here
+ bs_f st, st_subsequent
+m_event_done_addressing_write
+ call i2cmu_write_next_byte
+ bra_z m_event_write_mustfinish
+
+ now what ? fixme
+
+;----------
+m_event_write_mustfinish
+ bt_f_if0 st, st_subsequent
+ bra m_improper_write_finish
+
+ fixme
+
+;----------
+m_improper_write_finish
+ panic morse_SF
;======================================================================
; SLAVE
; TRISB<1,0> any configured for I2C
; SSPIP any configured correctly
; GIEL 0 (disabled) 0 (disabled)
+; ssp* shadows any all bits set
+ set_f sspstat
+ set_f sspcon1
+ set_f sspcon2
bs_f TRISB, 0
bs_f TRISB, 1
bc_f IPR1, SSPIP
; Some macros:
-chkvals_start macro
- mov_fw ssp
+chkvals_start_sspstat macro
+ mov_fw sspstat
chkval_lastvalue equ 0
endm
return
; We have an interrupt:
+ bt_f_if1 sspcon1, WCOL
+ bra_z s_event_bad
+ bt_f_if1 sspcon1, SSPOV
+ bra_z s_event_bad
+
; Firstly, clear the interrupt flag so that if something else happens
; while we faff, the interrupt will be regenerated:
bc_f PIR1, SSPIF
+ mov_ff SSPSTAT, sspstat
+ mov_ff SSPCON1, sspcon1
; Check that nothing obvious is wrong:
bsr check_wcolsspov
s_event_idle
chkvals_start
chkvals_addrrecv
-
- panic morse_SI
+s_event_bad
+ panic morse_SS
;========================================
; SLAVE - READING
;----------
s_event_reading
- chkvals_start
+ chkvals_start_sspstat
chkval 0xac, s_event_reading_datasent ; D,!P, S,R,!BF
; Whatever is happening, we're done reading now !
; Or, maybe it was nack and then we were reselected:
chkvals_addrrecv
- panic morse_SR
+ bra s_event_bad
;----------
s_event_reading_datasent
;----------
s_event_writing
- chkvals_start
+ chkvals_start_sspstat
chkval 0xa9, s_event_writing_datarecv ; D,!P, S,W,BF
; Well, we're done writing now in any case
; too picky.
; First, the nice cases:
- chkvals_start
+ chkvals_start_sspstat
chkvals_addrrecv
; Then random junk:
- mov_fw ssp
+ mov_fw sspstat
and_lw 0xc7 ; ?D_A, ?P; ?S
xor_lw 0x80 ; SMP, !CKE, !R_W, !UA, !BF
bt_f_if1 STATUS, Z
return
+ ; no good
- panic morse_SW
+ bra s_event_bad
;----------
s_event_writing_datarecv
TI5 ; for iwj
# Messages for i2clib, S*
+SM st, sspstat, sspcon1, sspcon2 ; master interrupt bad state
+SS st, sspstat, sspcon1 ; slave interrupt bad state
+SK slave ; m. couldn't address slave (no ack)
+SA slave ; improper slave address
+SW st ; improper master write start
+SF st ; improper master write finish
+
# in both
+
+SS sspstat, sspcon1,
+
SV SSPSTAT, ssp, st ; WCOL or SSPOV (ssp = SSPCON1, unusually)
# in master
+
+
SM SSPSTAT, SSPCON1, ssp, st ; interrupt with unexpected bits in SSPCON2
; (ssp = SSPCON2, unusually)
# in slave
+SS st, sspstat, sspcon1
+
+
SI ssp, SSPCON1 ; bad SSPSTAT when idle
SR ssp, SSPCON1 ; bad SSPSTAT when reading
SW ssp, SSPCON1 ; bad SSPSTAT when writing