chiark / gitweb /
Send HELLO as a result of all slaves being online. Do not crash if slave is slow...
[trains.git] / detpic / i2clib.inc
index 9e4b5e469a9804767797c3653e93511d4c1630cd..e91e31963f9ecdafd45d5fa945e6f2a660d8eed1 100644 (file)
@@ -44,8 +44,9 @@
 ; and State allows.
 
 ; All routines except i2c?_init must be called only:
-;   * During a low-priority interrupt;
-;   * From the main loop with low-priority interrupts disabled; or
+;   * During an appropriate interrupt (high-priority for the slave;
+;     low-priority for the master).
+;   * From the main loop with those interrupts disabled; or
 ;   * From within an i2c?u_... routine (which are always called
 ;     from within i2c?_interrupt).
 ; This is to avoid having one i2c_... routine running in an interrupt
@@ -58,7 +59,7 @@
 ; COMMON ADMINISTRATIVE ROUTINES
 
 ;--------------------
- extern i2cm_init
 extern i2cm_init
 ;
 ; Initialises the i2c system for use by a master PIC.  Must be called
 ; exactly once, which must be before any other i2c?_... function.
@@ -69,7 +70,7 @@
 ;   State                      Not-in-use              Idle (as master)
 
 ;--------------------
- extern i2cs_init
 extern i2cs_init
 ;
 ; Initialises the i2c system for use by a slave PIC.  Must be called
 ; exactly once, which must be before any other i2c?_... function.
 ;   W                          slave number            any
 
 ;--------------------
- extern i2cm_interrupt
- extern i2cs_interrupt
+  extern i2cm_interrupt
+  extern i2cm_interrupt_definite
+  extern i2cs_interrupt
 ;
-; Must be called by the main program's low priority interrupt handler.
-; The main program's interrupt handler is responsible for saving W and
-; the flags register and other interrupt-related administrivia.  If
-; there is an i2c interrupt, this routine will service it, taking any
-; necessary action including calling appropriate i2c?u_... routines,
-; and clear the interrupt flag[*].
+; Must be called by the main program's interrupt handler;
+; high-priority for the slave or low-priority for the master.
+;
+; For i2cm_interrupt, the main program's interrupt handler is
+; responsible for saving W and the flags register and other
+; interrupt-related administrivia.  i2cm_interrupt checks for
+; SSPIF and handles any interrupt.  i2cm_interrupt_definite
+; should only be called if SSPIF is set and handles it.  In
+; both cases the ISR returns with `return'.
+;
+; For i2cs_interrupt, it must be the only high-priority interrupt
+; source and expects to be called from the interrupt handler (and it
+; will return; the caller must retfie_r).
+;
+; If there is an i2c interrupt, the i2c?_interrupt will service it, taking
+; any necessary action including calling appropriate
+; i2c?u_... routines, and clear the interrupt flag[*].
 ;
 ;                              At call                 On return
 ;   State                      any except Not-in-use   may change
 ; [*] The interrupt event on entry, if any, will be dealt with.  If
 ; interrupt processing takes a long time, another interrupt will occur
 ; and this may result in the i2c interrupt flag being set on return
-; from i2c?_inerrupt.
+; from i2c?_interrupt.
 
 
 ;======================================================================
 ; MASTER
 ;
 ; States:
-;                      [Not-in-use]
-;                           |
-;                           |init
-;                                   v
-;                         [Idle]<-----------------------------.
-;              write_start/    \read_start                    |
-;                         /             \                             |
-;                       V        V                            |
-;            [Writing-Setup]    [Reading-Busy]<---------.      |
-;                   |                |                 |      |
-;    write_next_byte|                |read_got_byte    |      |
-;    must return NZ |                |                 |      |
-;                  V                 V                 |      |
-;           ,-->[Writing]         [Reading-Wait]       |      |
-;           `-------'  \           /     `-------------'      |
-;    write_next_byte    \         /       read_another        |
-;       returns NZ       |       /                            |
-;                        |       /read_done                           |
-;         write_next_byte|      |                             |
-;             returns Z  |      |                                     |
-;                        V      V                             |
-;                              [Stopping]                             |
-;                          |           done                   |
-;                          `----------------------------------'
+;                       [Not-in-use]
+;                            |
+;                            |init
+;                            v
+;                          [Idle]<-------------------------<------.
+;                           / \                                   |
+;                          / _ \ _____________________<______     |
+;                         /,'   \                            `.   |
+;             write_start//      \read_start                  |   |
+;                       //        \  ,------------------<---. |   |
+;                      //          \ |                      | |   |
+;                     VV            VV                      | |   |
+;            [Writing-Setup]   [Reading-Busy]<----------.   | |   |
+;                   |              |  |                 |   | |   |
+;                   |              |  |                 |   | |   |
+;                   |  slave_no_ack|  |                 |   | |   |
+;                   |      (1st    |  |                 |   | |   |
+;    write_next_byte|       byte  /   |read_got_byte    |   | |   |
+;    must return NZ |       only)/    |                 |   | |   |
+;                   V           /     V                 |   | |   |
+;           ,-->[Writing]      /  [Reading-Wait]        |   | |   |
+;           `-------'  \      |     / ||  `.___________,'   | |   |
+;    write_next_byte    \     |    /  ||   read_another     | |   |
+;       returns NZ       |    |   /   ||                    | |   |
+;                        |    |  /    |`.__________________,' |   |
+;                        |    | |     |        read_start     |   |
+;         write_next_byte|    | |     `._____________________,'   |
+;             returns Z  |    | |               write_start       |
+;                        |    | |read_done                        |
+;                        V    V V                                 |
+;                       [Stopping]                                |
+;                           |           done                      |
+;                           `-------------------------------------'
 
 ;--------------------
- extern i2cmu_done
 extern i2cmu_done
 
 ; Called to notify that the previous conversation with the slave has
 ; 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
 
+;--------------------
+  extern i2cmu_slave_no_ack
+
+; Called to notify that the slave did not acknowledge its address when
+; we attempted to read from it.  The i2c system is now clearing down
+; the i2c bus to prepare for another transaction.
+;
+;              Beforehand      At call
+;   State      Reading-Busy*   Stopping
+;
+;  * only Reading-Busy reached by calling read_start;
+;    not Reading-Busy due to read_another.
+
 ;========================================
 ; MASTER - WRITES (ie, transmission of data to the slave)
 
 ;--------------------
- extern i2cm_write_start
 extern i2cm_write_start
 ;
 ; Requests that a slave be contacted for writing.  When communication
 ; has been established, i2cmu_write_next_byte will be called.
 ;
 ;                              At call         On return
-;   State                      Idle            Writing-Setup
+;   State                   Idle/Reading-Wait  Writing-Setup
 ;   W                          slave number    any
 
- extern i2cmu_write_next_byte
 extern i2cmu_write_next_byte
 ;
 ; Called to notify the main program that we are now ready to transmit
 ; a byte to the slave that we're currently talking to.  This may be
 ; MASTER - READS (ie, reception of data from the slave)
 
 ;--------------------
- extern i2cm_read_start
 extern i2cm_read_start
 ;
 ; Requests that a slave be contacted for reading.  When communication
 ; has been established and the first byte received,
 ; i2cmu_read_got_byte will be called.
 ;
 ;                              At call         On return
-;   State                      Idle            Reading-Busy
+;   State                   Idle/Reading-Wait  Reading-Busy
 ;   W                          slave number    any
 
- extern i2cmu_read_got_byte
 extern i2cmu_read_got_byte
 ;
 ; Called to notify the main program that a byte has been recieved from
 ; the slave PIC.  The byte value is supplied.  Communication with the
 ;   State      Reading         Reading-Wait
 ;   W                          data from slave
 
- extern i2cm_read_another
 extern i2cm_read_another
 ;
 ; Requests that the communication with the slave continue and another
 ; byte be read.  When this is complete, i2cmu_read_got_byte will be
 ;                              At call         On return
 ;   State                      Reading-Wait    Reading-Busy
 
- extern i2cm_read_done
 extern i2cm_read_done
 ;
 ; Requests that reading from the slave be terminated.  When the
 ; conversation is finished and the bus and i2c controller are free
 ;                   [Not-in-use]
 ;                       |
 ;                       |init
-;                       v
-;                      [Idle]<-------------------------.
-;           write_begin/    \                          |
-;                    /      \read_begin               |
-;                   V        V                        |
-;        ,->[Receiving]      [Transmitting]<-.         |
-;               `-----'     |             |  `------'         |
-;    write_another   |             |   read_another    |
-;                   |    read_done|                   |
-;          write_done|             \                   |
-;                   `--------------+->----------------'
+;                       |
+;                       V
+;                      [Idle]
+;                       |
+;                       |<----------------------------.
+;                               +                             |
+;                       / \                           |
+;                      /   \                          |
+;          write_begin/     \read_begin                |
+;                    /       \                         |
+;                   V         V                        |
+;       ,->[Receiving]      [Transmit-Wait]<-.         |
+;       `-----'     |         |              |         |
+;     write_data    |         |read_data     |         |
+;                   |         V              |         |
+;                   |       [Transmit-Busy]  |         |
+;                   |         |       `------'         |
+;                   |         |        read_another    |
+;                   |         \                        |
+;                   `----------+->---------------------'
 
 ;========================================
 ; SLAVE - WRITES (ie, reception of data from the master)
 
 ;--------------------
- extern i2csu_write_begin
 extern i2csu_write_begin
 ;
 ; Called to notify the main program that the master PIC has selected this
-; slave to talk to, for writing.  Provides the first byte of data
-; we received from the master PIC.
+; slave to talk to, for writing.  There is no data at this stage; when
+; data is received, i2csu_write_data will be called.
 ;
 ;              Beforehand      At call                 On return
 ;   State      Idle            Receiving               Receiving
-;   W                          data from master        any
 
 ;--------------------
- extern i2csu_write_another
+  extern i2csu_write_data
 ;
-; Called to notify the main program that the master PIC has continued
-; by transmitting another byte of data.  Provides the byte we received.
+; Called to notify the main program that the master PIC has
+; transmitted a byte of data.  Provides the byte we received.
 ;
 ;              Beforehand      At call                 On return
 ;   State      Receiving       Receiving               Receiving
 ;   W                          data from master        any
 
-;--------------------
- extern i2csu_write_done
-;
-; Called to notify the main program that the master PIC has stopped
-; transmitting data (ie, finished the i2c conversation).
-;
-;              Beforehand      At call                 On return
-;   State      Receiving       Idle
-
 ;========================================
 ; SLAVE - READS (ie, transmission of data to the master)
 
 ;--------------------
- extern i2csu_read_begin
 extern i2csu_read_begin
 ;
 ; Called to notify the main program that the master PIC has selected
-; this slave to talk to, for reading, and to obtain the first byte of
-; data that we should transmit to the master.
+; this slave to talk to, for reading.  The main program should invoke
+; i2cs_read_data with first byte of data that we should transmit to
+; the master.
 ;
-;              Beforehand      At call                 On return
-;   State      Idle            Transmitting            Transmitting
-;   W                          any                     data for master
+;              Beforehand      At call
+;   State      Idle            Transmit-Wait
 
 ;--------------------
- extern i2csu_read_another
-;
-; Called to notify the main program that the master PIC has continued
-; by asking for another byte of data.  Must provide the byte.
+  extern i2cs_read_data
+; Transmits the byte of data to the master
 ;
 ;              Beforehand      At call                 On return
-;   State      Transmitting    Transmitting            Transmitting
-;   W                          any                     data for master
+;   State      Transmit-Wait   Transmit-Busy           Transmit-Busy
+;   W                          byte for master         any
+;
+; There is also a macro  i2cs_read_data_macro
+; in i2clib.incm, which does the same thing.
 
 ;--------------------
- extern i2csu_read_done
-;
-; Called to notify the main program that the master PIC has stopped
-; asking for data (ie, finished receiving).
+  extern i2csu_read_another
 ;
-;              Beforehand      At call                 On return
-;   State      Transmitting    Idle
-
-;======================================================================
-; INTERNAL VARIABLES
+; Called to notify the main program that the master PIC has continued
+; by asking for another byte of data.  The main program should once
+; more invoke i2cs_read_data.
 ;
-; 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
+;              Beforehand      At call
+;   State      Transmit-Busy   Transmit-Wait