chiark / gitweb /
i2c finished we think but not yet compiled
authorian <ian>
Wed, 16 Nov 2005 23:04:02 +0000 (23:04 +0000)
committerian <ian>
Wed, 16 Nov 2005 23:04:02 +0000 (23:04 +0000)
detpic/i2clib.asm
detpic/i2clib.inc
detpic/morse-auto.messages

index de07695fc90082d32bd6afcf6a1555a40e727c32..00196b9d6dbfe25f55098e5eefa4243101998b53 100644 (file)
@@ -7,24 +7,68 @@
  radix dec
  include ../iwjpictest/insn-aliases.inc
 
+;======================================================================
+; NOTATION
+
+; Naming conventions
+;
+;  m_...                       routines used by master only
+;  s_...                       routines used by slave only
+;  <any other name>            routines used by both
+;
+;  [ms]_event_...              event handler, branched to from interrupt
+;                               handler; conditions are as in the name;
+;                               should `return' at end which will return
+;                               from i2c[ms]_interrupt
+;
+;  [sm]_event_bad[_...]                event handler which panics; called when i2c
+;                               controller did something unexpected
+;
+;  m_improper_...              panics; called when main program
+;                               does something wrong
+;
+;  [ms]_<anything else>                routines or labels of some other kind
+
+; Whenever flow does not pass past the end of some code, we
+; have a boundary `;----------', and when flow passes past
+; an important label we sometimes mark it specially with `;...',
+; like this:
+;
+;              ;----------
+;              m_event_spong
+;                              bt_f_if0 i2c_st, st_something
+;                              bra     m_event_bad
+;              ;...
+;
+;              m_event_several_including_spong
+;                              bs_f    i2c_st, st_sponging
+;                              bra     metasyntacticing
+;
+;              ;----------
+;              m_event_wombat
+
 ;============================================================
 ; COMMON ADMINISTRATIVE ROUTINES and VARIABLES
 
                udata_acs
 
-sspstat                res     1
-sspcon1                res     1
-sspcon2                res     1       ; master only
-slave          res     1       ; master only
+i2c_sspstat            res     1
+i2c_sspcon1            res     1
+i2c_sspcon2            res     1       ; master only
+i2c_slave              res     1       ; master only
+
+i2c_st                 res     1
 
-st     res     1 ; bitmask, bit set in visible states:
+; i2c_st is a 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 ; 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?
+st_starting    equ 7 ; Writing-Setup?,Reading-Busy?
+st_addressing  equ 6 ; Writing-Setup?,Reading-Busy?
+st_writing     equ 5 ; Writing-*                       [Idle-going-]Receiving
+st_subsequent  equ 4 ; Writing?                        Receiving
+st_reading     equ 3 ; Reading-*                       Transmitting
+st_awaiting    equ 2 ; Reading-Wait
+st_acking      equ 1 ; Reading-Busy?,Stopping(from read)
+st_stopping    equ 0 ; Stopping
                  ; ...? means not always set in that state
 
                code
@@ -57,112 +101,243 @@ i2cm_interrupt
                return
                ; We have an interrupt:
 
-               mov_ff  SSPSTAT, sspstat
-               mov_ff  SSPCON1, sspcon1
-               mov_ff  SSPCON2, sspcon2
+               mov_ff  SSPSTAT, i2c_sspstat
+               mov_ff  SSPCON1, i2c_sspcon1
+               mov_ff  SSPCON2, i2c_sspcon2
 
-               bt_f_if1 sspcon1, WCOL
+               bt_f_if1 i2c_sspcon1, WCOL
                bra_z   m_event_bad
-               bt_f_if1 sspcon1, SSPOV
+               bt_f_if1 i2c_sspcon1, SSPOV
                bra_z   m_event_bad
 
                ; No ?  Well, then the I2C should be idle now:
-               mov_fw  sspcon2
+               mov_fw  i2c_sspcon2
                and_lw  ~0x60 ; ACKSTAT,ACKDT
                bra_nz  m_event_bad
                ; OK...
 
-               bt_f_if1 sspstat, R_W
+               bt_f_if1 i2c_sspstat, R_W
                bra_nz  m_event_bad
 
-               bt_f_if1 st, st_starting
+               bt_f_if1 i2c_st, st_stopping
+               bra     m_event_done_stopping
+
+               bt_f_if1 i2c_st, st_starting
                bra     m_event_done_starting
                ; not just done SEN
 
-               bt_f_if1 st, st_addressing
+               bt_f_if1 i2c_st, st_addressing
                bra     m_event_done_addressing
 
+               bt_f_if1 i2c_st, st_writing
+               bra     m_event_done_writing
+
+               bt_f_if1 i2c_st, st_acking
+               bra     m_event_done_acking
+
+               bt_f_if1 i2c_st, st_reading
+               bra     m_event_done_reading
+
 m_event_bad
-               panic   morse_SM
+               panic   morse_SM ; master, interrupt, controller in bad state
+
+;========================================
+; MASTER - STARTING, ADDRESSING, STOPPING
+
+;----------
+m_start
+;      i2c_st                  checked for busyness    correct
+;      st_reading/writing      set                     unchanged
+;      st_starting             clear                   set
+;      W                       slave number            any
+;      i2c_slave               any                     slave_number
+; expects to return directly to main program (caller)
+               mov_wf  i2c_slave
+               and_lw  31
+               bra_nz  m_improper_slave
+               bs_f    i2c_st, st_starting
+               bs_f    i2c_st, st_working
+               bs_f    SSPCON2, SEN
+               return
 
 ;----------
 m_event_done_starting
-               mov_fw  slave
+               mov_fw  i2c_slave
                bsr     slave2addr
 
-               bt_f_if1 st_reading
+               bt_f_if1 i2c_st, st_reading
                bs_w    0       ; address bottom bit means read
 
                mov_wf  SSPBUF
-               bc_f    st, st_starting
-               bs_f    st, st_addressing
+               bc_f    i2c_st, st_starting
+               bs_f    i2c_st, st_addressing
                return
 
 ;----------
 m_event_done_addressing
-               bt_f_if1 sspcon2, ACKSTAT
+               bt_f_if1 i2c_sspcon2, ACKSTAT
                bra     m_bad_address_ack
                ; OK, we got ack.
 
-               bc_f    st, st_addressing
-               bt_f_if1 st, st_reading
+               bc_f    i2c_st, st_addressing
+               bt_f_if1 i2c_st, st_reading
                bra     m_event_done_addressing_read
                bra     m_event_done_addressing_write
 
 ;----------
-m_bad_address_ack
-               panic   morse_SK
+m_stop
+;      st_stopping                     clear           set
+;      st_reading/acking/writing       any             unchanged
+; expects to return directly to main program or to end interrupt handler
+               bs_f    i2c_st, st_stopping
+               bs_f    SSPCON2, PEN
+               return
 
+;----------
+m_event_done_stopping
+               clr_f   i2c_st
+               goto    i2cmu_done
 
-               mov_fw  slave
-               bsr     slave2addr
+;----------
+m_bad_address_ack
+               panic   morse_SK
 
-               bt_f_if1 st_reading
-               bs_w    0       ; address bottom bit means read
+;----------
+m_improper_slave
+;      i2c_slave               slave number
+               panic   morse_SN
 
-               mov_wf  SSPBUF
-               bc_f    st, st_starting
-               bs_f    st, st_addressing
-               return
+;========================================
+; MASTER - WRITING
 
 ;----------
 i2cm_write_start
 ;                              At call         On return
 ;   State                      Idle            Writing-Setup
 ;   W                          slave number    any
-               tst_f_ifnz st
+               tst_f_ifnz i2c_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
+
+               bs_f    i2c_st, st_writing
+               bra     m_do_start
 
 ;----------
 m_event_done_writing
-               check for ack ?  check this when we bra here
-               bs_f    st, st_subsequent
+               ; Did slave ack our byte ?  It had better have done !
+               bt_f_if1 i2c_sspcon2, ACKSTAT
+               bra     m_event_bad
+
+               bs_f    i2c_st, st_subsequent
+;...
+
 m_event_done_addressing_write
+;      ACKSTAT         checked
+;      st_addressing   cleared
                call    i2cmu_write_next_byte
                bra_z   m_event_write_mustfinish
+               ; OK, we have the next byte:
 
-               now what ?  fixme
+               mov_wf  SSPBUF
+               return
 
 ;----------
 m_event_write_mustfinish
-               bt_f_if0 st, st_subsequent
+               bt_f_if0 i2c_st, st_subsequent
                bra     m_improper_write_finish
 
-               fixme
+               bra     m_stop
+
+;----------
+m_improper_write_start
+               panic   morse_SW
 
 ;----------
 m_improper_write_finish
                panic   morse_SF
 
+;========================================
+; MASTER - READING
+
+;----------
+i2cm_read_start
+;                              At call         On return
+;      State                   Idle            Reading-Busy
+;      W                       slave number    any
+               tst_f_ifnz i2c_st
+               bra     m_improper_read_start
+
+               bs_f    i2c_st, st_reading
+               bra     m_do_start
+
+;----------
+m_event_done_addressing_read
+m_event_done_acking_readmore
+;      ACKSTAT                 checked
+;      st_addressing/acking    cleared
+               bs_f    SSPCON2, RCEN
+               return
+
+;----------
+m_event_done_reading
+               bt_f_if0 i2c_sspstat, BF
+               bra     m_event_bad
+
+               mov_fw  SSPBUF
+
+               bs_f    i2c_st, st_awaiting
+               goto    i2cmu_read_got_byte
+
+;----------
+i2cm_read_another
+;   State                      Reading-Wait    Reading-Busy
+               bt_f_if0 i2c_st, st_awaiting
+               bra     m_improper_read_another
+               ; OK, we're fine to read another:
+;...
+
+m_read_ack
+;      st_reading              1 iff not done          unchanged
+;      st_awaiting             still set               cleared
+;      st_acking               clear                   set
+; expects to return directly to main program or to end interrupt handler
+               bc_f    i2c_st, st_awaiting
+               bs_f    i2c_st, st_acking
+               bc_f    SSPCON2, ACKDT ; ACKDT=0 means to acknowledge
+               bs_f    SSPCON2, ACKEN
+               return
+
+;----------
+i2cm_read_done
+;   State                      Reading-Wait    Stopping
+               bc_f    i2c_st, st_reading
+               
+               bt_f_if0 i2c_st, st_awaiting
+               bra     m_improper_read_done
+               ; OK:
+
+               bra     m_read_ack
+
+;----------
+m_event_done_acking
+               bc_f    i2c_st, st_acking
+
+               bt_f_if1 i2c_st, st_reading
+               bra     m_event_done_acking_readmore
+
+               bra     m_stop
+
+;----------
+m_improper_read_start
+               panic   morse_SR
+
+;----------
+m_improper_read_another
+               panic   morse_SA
+
+;----------
+m_improper_read_done
+               panic   morse_SD
+
 ;======================================================================
 ; SLAVE
 
@@ -171,7 +346,7 @@ i2cs_init
 ;      W               slave number            undefined
                rcall   slave2addr2
                mov_wf  SSPADD
-               clr_f   st
+               clr_f   i2c_st
                mov_lw  0x16 ; !SSPEN, CKP(release), I2C 7-bit slave no-SP-int
                mov_wf  SSPCON1
                mov_lw  0x01 ; !GCEN, SEN
@@ -189,9 +364,9 @@ ms_init_enable
 ;      SSPIP                   any                     configured correctly
 ;      GIEL                    0 (disabled)            0 (disabled)
 ;      ssp* shadows            any                     all bits set
-               set_f   sspstat
-               set_f   sspcon1
-               set_f   sspcon2
+               set_f   i2c_sspstat
+               set_f   i2c_sspcon1
+               set_f   i2c_sspcon2
                bs_f    TRISB, 0
                bs_f    TRISB, 1
                bc_f    IPR1, SSPIP
@@ -212,7 +387,7 @@ ms_init_enable
 ; Some macros:
 
 chkvals_start_sspstat macro
-               mov_fw  sspstat
+               mov_fw  i2c_sspstat
 chkval_lastvalue equ 0
                endm
 
@@ -233,38 +408,38 @@ i2cs_interrupt
                return
                ; We have an interrupt:
 
-               bt_f_if1 sspcon1, WCOL
+               bt_f_if1 i2c_sspcon1, WCOL
                bra_z   s_event_bad
-               bt_f_if1 sspcon1, SSPOV
+               bt_f_if1 i2c_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
+               mov_ff  SSPSTAT, i2c_sspstat
+               mov_ff  SSPCON1, i2c_sspcon1
 ; Check that nothing obvious is wrong:
                bsr     check_wcolsspov
 
-               bt_f_if0 st, st_reading
+               bt_f_if0 i2c_st, st_reading
                bra     s_event_reading
 
-               bt_f_if0 st, st_writing
+               bt_f_if0 i2c_st, st_writing
                bra     s_event_writing
 
 s_event_idle
                chkvals_start
                chkvals_addrrecv
 s_event_bad
-               panic   morse_SS
+               panic   morse_SS ; slave, interrupt, controller in bad state
 
 ;========================================
 ; SLAVE - READING
 
 ;----------
 s_event_idle_addrrecvread
-               bs_f    st, st_reading
+               bs_f    i2c_st, st_reading
                call    i2csu_read_begin
                bra     s_events_read_datasend
 
@@ -274,7 +449,7 @@ s_event_reading
                chkval  0xac, s_event_reading_datasent ; D,!P, S,R,!BF
 
                ; Whatever is happening, we're done reading now !
-               clr_f   st
+               clr_f   i2c_st
                call    i2csu_read_done
 
                chkval  0xa8, s_event_reading_datanack ; D,!P, S,!R,!BF
@@ -298,7 +473,7 @@ s_event_reading_datanack
 ;----------
 s_event_idle_addrrecvwrite
                bs_f    SSPCON, 3 ; we'll need the Stop interrupt
-               bs_f    st, st_writing
+               bs_f    i2c_st, st_writing
                ; well, this is all fine so far, so do carry on:
 
 s_write_slurpbyte
@@ -314,7 +489,7 @@ s_event_writing
                chkval  0xa9, s_event_writing_datarecv ; D,!P, S,W,BF
 
                ; Well, we're done writing now in any case
-               clr_f   st
+               clr_f   i2c_st
                bc_f    SSPCON1, 3 ; no Start and Stop interrupts any more
                call    i2csu_write_done
 
@@ -328,7 +503,7 @@ s_event_writing
                chkvals_addrrecv
 
                ; Then random junk:
-               mov_fw  sspstat
+               mov_fw  i2c_sspstat
                and_lw  0xc7 ; ?D_A, ?P; ?S
                xor_lw  0x80 ; SMP, !CKE, !R_W, !UA, !BF
                bt_f_if1 STATUS, Z
@@ -341,11 +516,11 @@ s_event_writing
 s_event_writing_datarecv
                rcall   s_write_slurpbyte
 
-               bt_f_if1 st, st_subsequent
+               bt_f_if1 i2c_st, st_subsequent
                goto    i2csu_write_another
                ; not subsequent (yet):
 
-               bs_f    st, st_subsequent
+               bs_f    i2c_st, st_subsequent
                goto    i2csu_write_begin
 
 ;======================================================================
index 8fbb578b57e0886aa82a1f762f77774b49f35008..9d24229748c20ce50e4961807a9f11db558c3641 100644 (file)
@@ -138,6 +138,11 @@ extern i2cmu_done
 ; been finished as requested.  The i2c system is now available and
 ; i2cm_*_start can be called.
 ;
+; (Note: If this arrangment means that main program ends up needing to
+; keep track of whether the I2C is Idle or not, it would probably be
+; straightforward to enhance the interface to be enhanced to make that
+; unnecessary, since this information is already tracked by i2clib.)
+;
 ;              Beforehand      At call
 ;   State      Stopping        Idle
 
@@ -319,3 +324,10 @@ extern i2csu_read_done
 ;   State      Transmitting    Idle
 
 ;======================================================================
+; INTERNAL VARIABLES
+;
+; these are `extern'd only so that the morse machinery can display them
+ extern i2c_sspstat
+ extern i2c_sspcon1
+ extern i2c_sspcon2
+ extern i2c_slave
index 19faa72b1b5cdcab74806f85e6634801413118ad..0705beac568bf759edb7284b51f00b041b301533 100644 (file)
@@ -32,38 +32,12 @@ TI4                         ; for iwj
 TI5                            ; for iwj
 
 # Messages for i2clib, S*
-SM     st, sspstat, sspcon1, sspcon2   ; master interrupt bad state
-SS     st, sspstat, sspcon1            ; slave interrupt bad state
+SM     i2c_st, sspstat, sspcon1, sspcon2
+SS     i2c_st, sspstat, sspcon1
 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
-
-
-
-SPW    st                      ; write_start when not permitted
-
-
-SA     SSPCON2                 ; Slave didn't I2C ack address
-SD     SSPCON2                 ; Slave didn't I2C ack data
+SN     slave                           ; improper slave number
+SW     i2c_st                          ; improper i2cm_write_start
+SF     i2c_st                          ; improper i2cmu_write_next_byte Z
+SR     i2c_st                          ; improper i2cm_read_start
+SA     i2c_st                          ; improper i2cm_read_another
+SD     i2c_st                          ; improper i2cm_read_done