Extension of original I2CSlave library to support multiple slave addresses and interrupts.

Files at this revision

API Documentation at this revision

Comitter:
jaerts
Date:
Sat Jul 12 15:09:06 2014 +0000
Child:
1:b7e586fffbf2
Commit message:
Initial version

Changed in this revision

I2CSlaveX.cpp Show annotated file Show diff for this revision Revisions of this file
I2CSlaveX.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/I2CSlaveX.cpp	Sat Jul 12 15:09:06 2014 +0000
@@ -0,0 +1,63 @@
+#include "I2CSlaveX.h"
+
+#if DEVICE_I2CSLAVE
+
+namespace mbed {
+
+I2CSlaveX* instance;
+
+I2CSlaveX::I2CSlaveX(PinName sda, PinName scl) : I2CSlave(sda, scl) {
+    
+}
+
+// Add optional index argument for slaves that accept multiple addresses
+void I2CSlaveX::address(int address, int idx) {
+    int addr = (address & 0xFF) | 1;
+    i2c_slave_address(&_i2c, idx, addr, 0);
+}
+
+// Add optional argument that will be set with the received data value (usually slave address)
+int I2CSlaveX::receive(char *data) {
+    if(data) {
+        *data = _i2c.i2c->DAT;
+    }
+    return i2c_slave_receive(&_i2c);
+}
+
+// Return read length rather than match/no match
+int I2CSlaveX::read(char *data, int length) {
+    return i2c_slave_read(&_i2c, data, length);
+}
+
+// Return write length rather than match/no match
+int I2CSlaveX::write(const char *data, int length) {
+    return i2c_slave_write(&_i2c, data, length);
+}
+
+void I2CSlaveX::attach(void (*fptr)(void)) {
+    if (fptr) {
+        _receive.attach(fptr);
+        enable_irq();
+    } else {
+        disable_irq();
+    }
+}
+
+void I2CSlaveX::_irq_handler(uint32_t id, uint8_t addr, uint8_t state) {
+    instance->_receive.call();
+}
+
+void I2CSlaveX::enable_irq() {
+    // Hacky way to call this instance
+    instance = this;
+    NVIC_SetVector(I2C_IRQn, (uint32_t)(&I2CSlaveX::_irq_handler));
+    NVIC_EnableIRQ(I2C_IRQn);    
+}
+
+void I2CSlaveX::disable_irq() {
+    NVIC_DisableIRQ(I2C_IRQn);    
+}
+
+}
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/I2CSlaveX.h	Sat Jul 12 15:09:06 2014 +0000
@@ -0,0 +1,102 @@
+#ifndef MBED_I2CSLAVEX_H
+#define MBED_I2CSLAVEX_H
+
+#include "mbed.h"
+
+namespace mbed {
+    
+/** An I2C Slave, used for communicating with an I2C Master device with support for Interrupts and multiple slave addresses
+ *
+ * Example:
+ * @code
+ * TBD EXAMPLE
+ * @endcode
+ */ 
+class I2CSlaveX : public I2CSlave
+{
+public:
+    /** Create an I2C Slave interface, connected to the specified pins.
+     *
+     *  @param sda I2C data line pin
+     *  @param scl I2C clock line pin
+     */
+    I2CSlaveX(PinName sda, PinName scl);
+ 
+    /** Checks to see if this I2C Slave has been addressed.
+     *
+     *  @returns
+     *  A status indicating if the device has been addressed, and how
+     *  - NoData            - the slave has not been addressed
+     *  - ReadAddressed     - the master has requested a read from this slave
+     *  - WriteAddressed    - the master is writing to this slave
+     *  - WriteGeneral      - the master is writing to all slave
+     */
+    int receive(char *data = NULL);
+
+    /** Read from an I2C master.
+     *
+     *  @param data pointer to the byte array to read data in to
+     *  @param length maximum number of bytes to read
+     *
+     *  @returns
+     *       0 on success,
+     *   non-0 otherwise
+     */
+    int read(char *data, int length);
+
+    /** Write to an I2C master.
+     *
+     *  @param data pointer to the byte array to be transmitted
+     *  @param length the number of bytes to transmite
+     *
+     *  @returns
+     *       0 on success,
+     *   non-0 otherwise
+     */
+    int write(const char *data, int length);
+
+    /** Sets the I2C slave address.
+     *
+     *  @param address The address to set for the slave (ignoring the least
+     *  signifcant bit). If set to 0, the slave will only respond to the
+     *  general call address.
+     */
+    void address(int address, int idx = 0);
+    
+    /** Attach a function to call when state changed event occured on the I2C peripheral
+     *
+     *  @param fptr A pointer to a void function, or 0 to set as none
+     */
+    void attach(void (*fptr)(void));
+
+    /** Attach a member function to call when state changed event occured on the I2C peripheral
+     *
+     *  @param tptr pointer to the object to call the member function on
+     *  @param mptr pointer to the member function to be called
+     */
+    template<typename T>
+    void attach(T* tptr, void (T::*mptr)(void)) {
+        _receive.attach(tptr, mptr);
+        enable_irq();
+    }
+    
+    /** Enable IRQ. This method depends on hw implementation, might enable one
+     *  port interrupts. For further information, check gpio_irq_enable().
+     */
+    void enable_irq();
+
+    /** Disable IRQ. This method depends on hw implementation, might disable one
+     *  port interrupts. For further information, check gpio_irq_disable().
+     */
+    void disable_irq();
+
+    static void _irq_handler(uint32_t id, uint8_t addr, uint8_t state);
+    
+protected:
+    FunctionPointer _receive;    
+    
+};
+
+}
+ 
+#endif