chiark / gitweb /
slave done?
authorian <ian>
Mon, 14 Nov 2005 01:42:41 +0000 (01:42 +0000)
committerian <ian>
Mon, 14 Nov 2005 01:42:41 +0000 (01:42 +0000)
detpic/i2clib.asm
detpic/morse-auto.messages

index b3ff2d371b83f4132889bb4ca17ae63c5a0015c0..101545cff720ada54828be7fdd38bcf118c40806 100644 (file)
@@ -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
index d9bef0df0a5c5990ea11050b411db7f9f64f792a..b83c3bf8c1a31599d79c4c61fa266da1fe023c9d 100644 (file)
@@ -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