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 8feda2866fa774a3632ef2d17aa54af7c0478641..e91e31963f9ecdafd45d5fa945e6f2a660d8eed1 100644 (file)
@@ -1,5 +1,5 @@
 ;######################################################################
-; i2clib.inc - I2C LIBRARY, DECLARATIONS AND DOCUMENTATION
+; i2clib.inc - I2C LIBRARY - DECLARATIONS AND DOCUMENTATION
 ;
 ;
 ;============================================================
@@ -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.
@@ -66,10 +67,10 @@ extern i2cm_init
 ;   i2c controller             any                     for use by i2clib
 ;   i2c interrupt config       any                     enabled, low priority
 ;   global interrupt enable    disabled                unchanged
-;   State                      Not-in-use              Idle
+;   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.
@@ -78,18 +79,31 @@ extern i2cs_init
 ;   i2c controller             any                     for use by i2clib
 ;   i2c interrupt config       any                     enabled, low priority
 ;   global interrupt enable    disabled                unchanged
-;   State                      Not-in-use              Idle
+;   State                      Not-in-use              Idle (as slave)
 ;   W                          slave number            any
 
-extern i2cs_interrupt
-extern i2cm_interrupt
+;--------------------
+  extern i2cm_interrupt
+  extern i2cm_interrupt_definite
+  extern i2cs_interrupt
+;
+; 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'.
 ;
-; 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[*].
+; 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
@@ -98,7 +112,159 @@ extern i2cm_interrupt
 ; [*] 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                  |   |
+;                       //        \  ,------------------<---. |   |
+;                      //          \ |                      | |   |
+;                     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
+
+; 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.
+;
+;              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
+;
+; 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/Reading-Wait  Writing-Setup
+;   W                          slave number    any
+
+  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
+; either because i2cm_write_start was previously called and
+; communication has been established, or because tranmission of the
+; previous byte is complete.
+;
+; The main program must immediately supply the actual data byte.  This
+; byte will then be transmitted to the slave, and then
+; i2cmu_write_next_byte will be called again.
+
+; Alternatively the main program may indicate that the tranmission
+; should finish by setting the Z flag on return.  In this case the
+; slave will be told that this is the end of the message and the i2c
+; conversation will be finished.  When the conversation is finished
+; and the bus and i2c controller are free again, i2cmu_done will be
+; called.
+;
+;  When transmission should continue:
+;
+;              Beforehand      At call         On return       After return
+;   State      Writing[-Setup] Writing         Writing         Writing
+;   Status Z                   any             0 (NZ, not zero, not equal)
+;   W                          any             data for slave
+;
+;  When transmission should finish:
+;
+;              Beforehand      At call         On return       After return
+;   State      Writing         Writing         Writing         Stopping
+;   Status Z                   any             1 (Z, zero, equal)
+;   W                          any             any
+
+;========================================
+; MASTER - READS (ie, reception of data from the slave)
+
+;--------------------
+  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-Wait  Reading-Busy
+;   W                          slave number    any
+
+  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
+; slave will be suspended (with the i2c bus blocked) until the main
+; program calls i2cm_read_another or i2cm_read_done.  The main program
+; must call one of these two before doing anything else with the i2c.
+;
+;              Beforehand      At call
+;   State      Reading         Reading-Wait
+;   W                          data from slave
+
+  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
+; called.
+;
+;                              At call         On return
+;   State                      Reading-Wait    Reading-Busy
+
+  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
+; again, i2cmu_done will be called.
+;
+;                              At call         On return
+;   State                      Reading-Wait    Stopping
 
 
 ;======================================================================
@@ -108,108 +274,82 @@ extern i2cm_interrupt
 ;
 ;                   [Not-in-use]
 ;                       |
-;                       |init                     
-;                       v                         
-;                      [Idle]<-------------------------.
-;           write_begin/    \                          |
-;                    /      \read_begin               |
-;                   V        V                        |
-;        ,->[Receiving]      [Transmitting]<-.         |
-;               `-----'     |             |  `------'         |
-;    write_another   |             |   read_another    |
-;                   |    read_done|                   |
-;          write_done|             \                   |
-                    `--------------+->----------------'
+;                       |init
+;                       |
+;                       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
-
-;--------------------
-extern i2csu_read_done
+;   State      Transmit-Wait   Transmit-Busy           Transmit-Busy
+;   W                          byte for master         any
 ;
-; Called to notify the main program that the master PIC has stopped
-; asking for data (ie, finished receiving).
-;
-;              Beforehand      At call                 On return
-;   State      Transmitting    Idle
-
-
-
-
-
-; junky bits after here need turning into MASTER sections.
-
+; There is also a macro  i2cs_read_data_macro
+; in i2clib.incm, which does the same thing.
 
+;--------------------
+  extern i2csu_read_another
 ;
-; i2cm_write_start
-;      slave no.
-;   causes
-; i2cmu_write_next_byte
-;      must return byte to transmit
-;      must say whether to stop
-;   stop causes
-; i2cmu_done
+; 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.
 ;
-; i2cm_read_start
-;      slave no.
-;   causes
-; i2cmu_read_got_byte
-;      byte value
-;   causes
-; i2cm_read_another or i2cm_read_done
-;  causes               causes
-;  i2cmu_done          i2cmu_done
+;              Beforehand      At call
+;   State      Transmit-Busy   Transmit-Wait