udata_acs
-t res 1
+ssp res 1
st res 1 ; bitmask:
st_writing equ 0
i2cs_interrupt
bt_f_if0 PIR1, SSPIF
return
+ ; We have an interrupt:
-; We have an interrupt. Firstly, clear the interrupt flag
-; so that if something else happens while we faff, the interrupt
-; will be regenerated:
+; Firstly, clear the interrupt flag so that if something else happens
+; while we faff, the interrupt will be regenerated:
bc_f PIR1, SSPIF
-; Check that nothing is wrong:
+; Check that nothing obvious is wrong:
mov_fw SSPCON1
- mov_wf t
+ mov_wf ssp
and_lw 0xc0
bra_nz i2cs_interrupt_wcolsspov_endif
panic morse_SV
i2cs_interrupt_wcolsspov_endif
; Find out what's just happened:
- mov_ff SSPSTAT, t
+ mov_ff SSPSTAT, ssp
; bits we want to check
; 80 60 20 10 08 04 02 01
; SMP CKE D_A P S R_W UA BF
; set clr data? stop start read? clr full?
-chkvalm macro mask, value, label
- mov_fw t
- xor_lw value
- bra_z label
- endm
-
- chkvalm 0xdf, 0x90, s_case_something_stop
- chkvalm 0xdb, 0x88, s_case_uninteresting_start
-
- mov_fw t
-
+ mov_fw ssp
chkval_lastvalue equ 0
+
chkval macro value, label
xor_lw value ^ chkval_lastvalue
chkval_lastvalue equ value
chkval 0x89, s_case_addr_recv_write
chkval 0x8d, s_case_addr_recv_read
chkval 0xa9, s_case_write_data_recv
+
+ bt_f_if0 st, st_reading
+ bra s_ifnot_reading
+
+ ; only check this if we're reading; otherwise
+ ; this will be handled by s_case_uninteresting_start
chkval 0xac, s_case_read_data_sent
chkval 0xa8, s_case_read_data_nack
- mov_ff t, WREG2 ; fixme
+s_ifnot_reading
+
+chkvalm macro mask, value, label
+ mov_fw ssp
+ xor_lw value
+ bra_z label
+ endm
+
+ chkvalm 0xdf, 0x90, s_case_something_stop
+ chkvalm 0xdb, 0x88, s_case_uninteresting_start
+
+ mov_ff ssp, WREG2 ; fixme
panic morse_SS
;----------
s_case_something_stop
- bc_f SSPCON1, 3 ; disable Start and Stop interrupts
+s_case_something_start
+s_ensure_idle
+ mov_fw st ; were we doing something ?
+ bt_f_if1 STATUS,Z
+ return
+ ; we were, it seems:
- ; Were we receiving ?
- bt_f_if0 st, st_writing
- bra s_caseshare_something_uninteresting
+ bc_f SSPCON, 3
+ clr_f st
+ ; now we're not (but W still has old st)
- ; Yes, we were receiving:
- clr_f st ; now we're idle
+ bt_f_if1 WREG, st_writing
goto i2csu_write_done
- ; tail call; we couldn't do anything after that
- ; anyway since it might well reenter us.
-;----------
-s_case_something_start
- bc_f SSPCON, 3 ; disable Start and Stop interrupts
-s_caseshare_something_uninteresting
- tst_f_ifnz st ; were we doing something ?
- bra s_panic_st_unexpected
- return
+ bt_f_if1 WREG, st_reading
+ goto i2csu_read_done
+
+ mov_wf st ; put it back and then ...
s_panic_st_unexpected
panic morse_ST
;----------
s_case_addr_recv_write
+ rcall s_ensure_idle
bs_f SSPCON, 3; we'll need the Stop interrupt
bs_f st, st_writing
-s_case_addr_recv_read
- ; well, this is all just fine so do carry on
- rcall s_write_slurpbyte
+ ; well, now this is all fine so do carry on:
s_write_slurpbyte
; W any byte from master
bt_f_if0 st, st_writing
bra s_panic_st_unexpected
; ok, we are writing:
+
rcall s_write_slurpbyte
+
bt_f_if1 st, st_subsequent
goto i2csu_write_another
- ; not subsequent:
+ ; not subsequent (yet):
+
bs_f st, st_subsequent
goto i2csu_write_begin
+;----------
+s_case_addr_recv_read
+ rcall s_ensure_idle
+ bs_f st, st_reading
+ call i2csu_read_begin
+ bra s_cases_read_data_send
+
;----------
s_case_read_data_sent
+ call i2csu_read_another
+
+s_cases_read_data_send
+ mov_wf SSPBUF
+ bs_f SSPCON1, CKP
+ return
+
+;----------
+s_case_read_data_nack
+ rcall s_ensure_idle
+ goto i2csu_read_done
-s_caseshare_write_alliswell
+s_cases_write_alliswell
- bt_f_if1 t, I2C_START
+ bt_f_if1 ssp, I2C_START
bra si_if_start
si_if_notstart
; So it should be stop
- mov_fw t
+ mov_fw ssp
and_lw 0xdf ; ?D_A
xor_lw 0x90 ; SMP, !CKE, P; !S, !R_W, !UA, !BF
bra_nz si_if_bad
si_if_start
- bt_f_if1 t, BF
+ bt_f_if1 ssp, BF
bra si_if_bufferfull
si_if_bufferempty
- bt_f_if1 t, R_W ;read?
+ bt_f_if1 ssp, R_W ;read?
bra si_if_bufferempty_reading
si_if_bufferempty_notreading
; So we think this is just a START (which we want to ignore)
- mov_fw t
+ mov_fw ssp
and_lw 0xdf ; ?D_A
xor_lw 0x88 ; SMP, !CKE, !P; S, !R_W, !UA, !BF
bra_nz si_if_bad
and_lw 0xfe
bra_nz nonzero
- mov_wf t
+ mov_wf ssp
mov_fw SSPSTAT