From: ian Date: Mon, 14 Nov 2005 01:42:41 +0000 (+0000) Subject: slave done? X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=545d5f4ea0afce8e9a9208ea9471502e0ca50d45;p=trains.git slave done? --- diff --git a/detpic/i2clib.asm b/detpic/i2clib.asm index b3ff2d3..101545c 100644 --- a/detpic/i2clib.asm +++ b/detpic/i2clib.asm @@ -8,7 +8,7 @@ include ../iwjpictest/insn-aliases.inc ;============================================================ -; COMMON ADMINISTRATIVE ROUTINES +; COMMON ADMINISTRATIVE ROUTINES and VARIABLES udata_acs @@ -20,13 +20,26 @@ st_subsequent equ 0 code -;-------------------- +;---------- +slave2addr +; computes slave address in form suitable for use in i2c controller +; actual i2c slave address is (slave number) + 0b0001000 +; W slave number i2c address * 2 + add_lw 0b0001000 + rlc_w + return + + +;====================================================================== +; SLAVE + +;---------- i2cs_init ; W slave number undefined rcall slave2addr2 mov_wf SSPADD clr_f st - mov_lw 0x1e ; !SSPEN, CKP(release), I2C 7-bit slave S&P + mov_lw 0x16 ; !SSPEN, CKP(release), I2C 7-bit slave no-SP-int mov_wf SSPCON1 mov_lw 0x01 ; !GCEN, SEN mov_wf SSPCON2 @@ -39,7 +52,35 @@ i2cs_init bs_f PIE1, SSPIE return -;-------------------- +;======================================== +; SLAVE - INTERRUPT HANDLING + +; In general, we figure out our state and then see what kind of events +; we were expecting. 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? +; (we don't usually mention SMP, CKE and UA below) + +; Some macros: + +chkvals_start macro + mov_fw ssp +chkval_lastvalue equ 0 + endm + +chkval macro value, label + xor_lw value ^ chkval_lastvalue + chkval_lastvalue equ value + bra_z label + endm + +chkvals_addrrecv macro + chkval 0x8c, s_event_idle_addrrecvread ; A,!P, S,R,!BF + chkval 0x89, s_event_idle_addrrecvwrite ; A,!P, S,W,BF + endm + +;---------- i2cs_interrupt bt_f_if0 PIR1, SSPIF return @@ -52,83 +93,64 @@ i2cs_interrupt ; Check that nothing obvious is wrong: mov_fw SSPCON1 mov_wf ssp - and_lw 0xc0 + and_lw 0xc0 ; WCOL, SSPOV bra_nz i2cs_interrupt_wcolsspov_endif panic morse_SV i2cs_interrupt_wcolsspov_endif -; Find out what's just happened: - 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? - - mov_fw ssp -chkval_lastvalue equ 0 - -chkval macro value, label - xor_lw value ^ chkval_lastvalue - chkval_lastvalue equ value - bra_z label - endm - - 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 + bra s_event_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 + bt_f_if0 st, st_writing + bra s_event_writing -s_ifnot_reading +s_event_idle + chkvals_start + chkvals_addrrecv -chkvalm macro mask, value, label - mov_fw ssp - xor_lw value - bra_z label - endm + panic morse_SI - chkvalm 0xdf, 0x90, s_case_something_stop - chkvalm 0xdb, 0x88, s_case_uninteresting_start +;======================================== +; SLAVE - READING - mov_ff ssp, WREG2 ; fixme - panic morse_SS +;---------- +s_event_idle_addrrecvread + bs_f st, st_reading + call i2csu_read_begin + bra s_events_read_datasend ;---------- -s_case_something_stop -s_case_something_start -s_ensure_idle - mov_fw st ; were we doing something ? - bt_f_if1 STATUS,Z - return - ; we were, it seems: +s_event_reading + chkvals_start + chkval 0xac, s_event_reading_datasent ; D,!P, S,R,!BF - bc_f SSPCON, 3 + ; Whatever is happening, we're done reading now ! clr_f st - ; now we're not (but W still has old st) + call i2csu_read_done - bt_f_if1 WREG, st_writing - goto i2csu_write_done + chkval 0xa8, s_event_reading_datanack ; D,!P, S,!R,!BF + ; Or, maybe it was nack and then we were reselected: + chkvals_addrrecv - bt_f_if1 WREG, st_reading - goto i2csu_read_done + panic morse_SR - mov_wf st ; put it back and then ... +;---------- +s_event_reading_datasent + call i2csu_read_another +s_events_reading_datasend + mov_wf SSPBUF + bs_f SSPCON1, CKP +s_event_reading_datanack + return -s_panic_st_unexpected - panic morse_ST +;======================================== +; SLAVE - WRITING ;---------- -s_case_addr_recv_write - rcall s_ensure_idle - bs_f SSPCON, 3; we'll need the Stop interrupt +s_event_idle_addrrecvwrite + bs_f SSPCON, 3 ; we'll need the Stop interrupt bs_f st, st_writing - ; well, now this is all fine so do carry on: + ; well, this is all fine so far, so do carry on: s_write_slurpbyte ; W any byte from master @@ -138,122 +160,45 @@ s_write_slurpbyte return ;---------- -s_case_write_data_recv - bt_f_if0 st, st_writing - bra s_panic_st_unexpected - ; ok, we are writing: +s_event_writing + chkvals_start + chkval 0xa9, s_event_writing_datarecv ; D,!P, S,W,BF - rcall s_write_slurpbyte - - bt_f_if1 st, st_subsequent - goto i2csu_write_another - ; 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_cases_write_alliswell - + ; Well, we're done writing now in any case + clr_f st + bc_f SSPCON1, 3 ; no Start and Stop interrupts any more + call i2csu_write_done + ; Who knows what might have happened. We may have + ; missed a number of S and P due to delay between + ; clearing SSPIF and SSPM3(s&p-intrs) so we can't be + ; too picky. - bt_f_if1 ssp, I2C_START - bra si_if_start + ; First, the nice cases: + chkvals_start + chkvals_addrrecv -si_if_notstart - ; So it should be stop + ; Then random junk: 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 ssp, BF - bra si_if_bufferfull -si_if_bufferempty - 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 ssp - and_lw 0xdf ; ?D_A - xor_lw 0x88 ; SMP, !CKE, !P; S, !R_W, !UA, !BF - bra_nz si_if_bad - - ; OK, ignore it + and_lw 0xc7 ; ?D_A, ?P; ?S + xor_lw 0x80 ; SMP, !CKE, !R_W, !UA, !BF + bt_f_if1 STATUS, Z return - - - - -;---------- -s_case_unknown_stop -s_case_unknown_start - return + panic morse_SW ;---------- -s_case_got_write_addr - - - mov_fw SSPBUF - and_lw 0xfe - bra_nz nonzero - - mov_wf ssp - - - mov_fw SSPSTAT - and_lw 0xe7 ; all except P and S - - xor_lw 0x80 - ; bits which might sensibly be set - -chkval_last equ 0 -chkval macro value, label - xor_lw value ^ chkval_last - bra_z label -chkval_last equ value - endm - chkval 0x80 ; addr dunno - - mov_lw 0x8 - - - bt_f_if0 DATA_ADDRESS, SSPSTAT - bra data - -slave2addr -; computes slave address in form suitable for use in i2c controller -; actual i2c slave address is (slave number) + 0b0001000 -; W slave number i2c address * 2 - add_lw 0b0001000 - rlc_w - return +s_event_writing_datarecv + rcall s_write_slurpbyte + bt_f_if1 st, st_subsequent + goto i2csu_write_another + ; not subsequent (yet): + bs_f st, st_subsequent + goto i2csu_write_begin +;====================================================================== include i2clib.inc end diff --git a/detpic/morse-auto.messages b/detpic/morse-auto.messages index d9bef0d..b83c3bf 100644 --- a/detpic/morse-auto.messages +++ b/detpic/morse-auto.messages @@ -32,9 +32,13 @@ TI4 ; for iwj TI5 ; for iwj # Messages for i2clib, S* -SV SSPSTAT, t ; WCOL or SSPOV -SS t, SSPCON1 ; slave got i2c interrupt but bad SSPSTAT -ST t, st ; slave got i2c interrupt but bad st +SV SSPSTAT, ssp ; WCOL or SSPOV (ssp = SSPCON1, unusually) +SI ssp, SSPCON1 ; bad SSPSTAT when idle +SR ssp, SSPCON1 ; bad SSPSTAT when reading +SW ssp, SSPCON1 ; bad SSPSTAT when writing + +SS ssp, SSPCON1 ; slave got i2c interrupt but bad SSPSTAT +ST ssp, st ; slave got i2c interrupt but bad st SA SSPCON2 ; Slave didn't I2C ack address SD SSPCON2 ; Slave didn't I2C ack data