This software drives a PCA9675 device via an I2C bus. Included functions allow you to read the device ID, set the IO direction, and read and write from the device.

Dependencies:   mbed

Revision:
0:3331b5950572
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/PCA9675.cpp	Tue Nov 23 10:59:14 2010 +0000
@@ -0,0 +1,139 @@
+/* C++ Source Code for PCA9675 I2C 16bit IO latch */
+/* ********************************************** */
+
+
+#include "misra_types.h"
+#include "mbed.h"
+#include "PCA9675.h"
+
+
+
+
+/* Constructor */
+PCA9675::PCA9675(I2C *Selected_I2C_Channel, uint8_t Slave_Address)
+    {
+        My_Local_I2C = Selected_I2C_Channel;
+        My_Lcoal_Slave_Address = Slave_Address;
+    }
+
+/* Destructor */
+PCA9675::~PCA9675()
+    {
+    }
+    
+
+
+/* Setup and configure the I/O latch */
+sint32_t PCA9675::init(uint8_t Port0_Direction, uint8_t Port1_Direction)
+    {
+        sint32_t Ack_Status = eI2C_ACK;
+
+        Ack_Status = reset();                                                   /* Reset the device */
+        My_Local_Port0_Direction = Port0_Direction;                             /* Keep a copy of the port0 direction */
+        My_Local_Port1_Direction = Port1_Direction;                             /* Keep a copy of the port1 direction */
+        
+        if (Ack_Status == eI2C_ACK)
+            {
+                Ack_Status = write_data(Port0_Direction, Port1_Direction);      /* This configures the I/O direction: each bit: 0=output, 1=inout  */
+            }
+             
+        return Ack_Status;
+    }        
+
+    
+
+
+/* Reset the device */                
+sint32_t PCA9675::reset()
+    {
+        sint32_t Ack_Status = eI2C_ACK;
+        sint8_t reset_command = ePCA9675_RESET_COMMAND;                         /* Reset command following a general call, address 0 will reset the device */
+
+        Ack_Status = My_Local_I2C -> write(ePCA9675_RESET_ADDRESS << 1, &reset_command, 1, eI2C_NO_REPEATED_START); 
+                                                                                                
+        return Ack_Status;                                                                                        
+    }                                    
+
+
+/* Write two byte of data to the device */
+sint32_t PCA9675::write_data(uint8_t port0_payload, uint8_t port1_payload)
+    {
+        sint32_t Ack_Status = eI2C_ACK;
+        sint8_t tx_array[2];                                                   /* Local array of data to be transmitted */
+        
+        /* If we try and write a 0/1 to a pin that is designated an input we must force the state to a 1(input) */
+        /* as the device is quasi birectional */
+        /* This is to avoid turning the pin from a designated input into an output by mistake */
+        /* If the pin is designated as input and we have logic 1 on the input we and indvertantly write a 0 to it */
+        /* then we will have a large current flow input the pin */
+        /* Hence the 'or' block below prevents unwanted damage to the pin */
+        /* Quasi direction is: 1 = input, 0 = output */
+        port0_payload = (port0_payload | My_Local_Port0_Direction);
+        port0_payload = (port1_payload | My_Local_Port1_Direction);
+        
+        tx_array[ePCA9675_PORT0] = port0_payload;                              /* First is for Port 0 */
+        tx_array[ePCA9675_PORT1] = port1_payload;                              /* Second is for Port 1 */
+ 
+        Ack_Status = My_Local_I2C -> write(My_Lcoal_Slave_Address << 1, tx_array, 2, eI2C_NO_REPEATED_START);  
+        return Ack_Status;
+    }
+
+
+/* Read two bytes from the device */
+sint32_t PCA9675::read_data(uint8_t *read_port0, uint8_t *read_port1)
+    {
+        sint32_t Ack_Status = eI2C_ACK;
+        sint8_t rx_array[2];                                                   /* Local reception array */
+
+        Ack_Status = My_Local_I2C -> read(My_Lcoal_Slave_Address << 1, rx_array, 2, eI2C_NO_REPEATED_START); 
+
+        *read_port0 = rx_array[ePCA9675_PORT0];                               /* transfer data back to pointer */
+        *read_port1 = rx_array[ePCA9675_PORT1];                               /* transfer data back to pointer */
+        return Ack_Status;
+    }        
+
+
+/* Read the device ID */
+sint32_t PCA9675::read_device_ID(uint8_t *manufacturer, uint16_t *part_ident, uint8_t *die_revision)
+
+    {
+        sint32_t Ack_Status = eI2C_ACK;
+        sint8_t rx_array[3] = {0,0,0};
+        uint32_t temp_value = 0;
+        sint8_t tx_array = (My_Lcoal_Slave_Address << 1);
+
+      
+        Ack_Status = My_Local_I2C -> write(0xF8, &tx_array, 1, eI2C_REPEATED_START);
+        Ack_Status = My_Local_I2C ->  read(0xF9, rx_array,  3, eI2C_NO_REPEATED_START);            
+      
+        temp_value = rx_array[0];
+        temp_value = (temp_value << 8);
+        
+        temp_value = (temp_value | rx_array[1]);
+        temp_value = (temp_value << 8);
+        
+        temp_value = (temp_value | rx_array[2]);
+        
+        
+        *die_revision = (uint8_t) (temp_value & 0x00000003);                            /* 3 LSB bits are die revision */
+        temp_value = (temp_value >> 3);
+        
+        *part_ident = (uint16_t) (temp_value & 0x00001FFF);                               /* Next 13 bits are part identification */
+        temp_value = (temp_value >> 13);
+        
+        *manufacturer = (uint8_t) (temp_value & 0x000000FF);                               /* Next 8 bits are manufacturers name */
+
+        return Ack_Status;
+    }        
+
+
+
+
+/* Read the configured slave address */
+uint8_t PCA9675::read_slave_address()
+    {
+        return My_Lcoal_Slave_Address;
+    }                                           
+        
+        
+