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

Committer:
DavidGilesHitex
Date:
Tue Nov 23 10:59:14 2010 +0000
Revision:
0:3331b5950572

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DavidGilesHitex 0:3331b5950572 1 /* C++ Source Code for PCA9675 I2C 16bit IO latch */
DavidGilesHitex 0:3331b5950572 2 /* ********************************************** */
DavidGilesHitex 0:3331b5950572 3
DavidGilesHitex 0:3331b5950572 4
DavidGilesHitex 0:3331b5950572 5 #include "misra_types.h"
DavidGilesHitex 0:3331b5950572 6 #include "mbed.h"
DavidGilesHitex 0:3331b5950572 7 #include "PCA9675.h"
DavidGilesHitex 0:3331b5950572 8
DavidGilesHitex 0:3331b5950572 9
DavidGilesHitex 0:3331b5950572 10
DavidGilesHitex 0:3331b5950572 11
DavidGilesHitex 0:3331b5950572 12 /* Constructor */
DavidGilesHitex 0:3331b5950572 13 PCA9675::PCA9675(I2C *Selected_I2C_Channel, uint8_t Slave_Address)
DavidGilesHitex 0:3331b5950572 14 {
DavidGilesHitex 0:3331b5950572 15 My_Local_I2C = Selected_I2C_Channel;
DavidGilesHitex 0:3331b5950572 16 My_Lcoal_Slave_Address = Slave_Address;
DavidGilesHitex 0:3331b5950572 17 }
DavidGilesHitex 0:3331b5950572 18
DavidGilesHitex 0:3331b5950572 19 /* Destructor */
DavidGilesHitex 0:3331b5950572 20 PCA9675::~PCA9675()
DavidGilesHitex 0:3331b5950572 21 {
DavidGilesHitex 0:3331b5950572 22 }
DavidGilesHitex 0:3331b5950572 23
DavidGilesHitex 0:3331b5950572 24
DavidGilesHitex 0:3331b5950572 25
DavidGilesHitex 0:3331b5950572 26 /* Setup and configure the I/O latch */
DavidGilesHitex 0:3331b5950572 27 sint32_t PCA9675::init(uint8_t Port0_Direction, uint8_t Port1_Direction)
DavidGilesHitex 0:3331b5950572 28 {
DavidGilesHitex 0:3331b5950572 29 sint32_t Ack_Status = eI2C_ACK;
DavidGilesHitex 0:3331b5950572 30
DavidGilesHitex 0:3331b5950572 31 Ack_Status = reset(); /* Reset the device */
DavidGilesHitex 0:3331b5950572 32 My_Local_Port0_Direction = Port0_Direction; /* Keep a copy of the port0 direction */
DavidGilesHitex 0:3331b5950572 33 My_Local_Port1_Direction = Port1_Direction; /* Keep a copy of the port1 direction */
DavidGilesHitex 0:3331b5950572 34
DavidGilesHitex 0:3331b5950572 35 if (Ack_Status == eI2C_ACK)
DavidGilesHitex 0:3331b5950572 36 {
DavidGilesHitex 0:3331b5950572 37 Ack_Status = write_data(Port0_Direction, Port1_Direction); /* This configures the I/O direction: each bit: 0=output, 1=inout */
DavidGilesHitex 0:3331b5950572 38 }
DavidGilesHitex 0:3331b5950572 39
DavidGilesHitex 0:3331b5950572 40 return Ack_Status;
DavidGilesHitex 0:3331b5950572 41 }
DavidGilesHitex 0:3331b5950572 42
DavidGilesHitex 0:3331b5950572 43
DavidGilesHitex 0:3331b5950572 44
DavidGilesHitex 0:3331b5950572 45
DavidGilesHitex 0:3331b5950572 46 /* Reset the device */
DavidGilesHitex 0:3331b5950572 47 sint32_t PCA9675::reset()
DavidGilesHitex 0:3331b5950572 48 {
DavidGilesHitex 0:3331b5950572 49 sint32_t Ack_Status = eI2C_ACK;
DavidGilesHitex 0:3331b5950572 50 sint8_t reset_command = ePCA9675_RESET_COMMAND; /* Reset command following a general call, address 0 will reset the device */
DavidGilesHitex 0:3331b5950572 51
DavidGilesHitex 0:3331b5950572 52 Ack_Status = My_Local_I2C -> write(ePCA9675_RESET_ADDRESS << 1, &reset_command, 1, eI2C_NO_REPEATED_START);
DavidGilesHitex 0:3331b5950572 53
DavidGilesHitex 0:3331b5950572 54 return Ack_Status;
DavidGilesHitex 0:3331b5950572 55 }
DavidGilesHitex 0:3331b5950572 56
DavidGilesHitex 0:3331b5950572 57
DavidGilesHitex 0:3331b5950572 58 /* Write two byte of data to the device */
DavidGilesHitex 0:3331b5950572 59 sint32_t PCA9675::write_data(uint8_t port0_payload, uint8_t port1_payload)
DavidGilesHitex 0:3331b5950572 60 {
DavidGilesHitex 0:3331b5950572 61 sint32_t Ack_Status = eI2C_ACK;
DavidGilesHitex 0:3331b5950572 62 sint8_t tx_array[2]; /* Local array of data to be transmitted */
DavidGilesHitex 0:3331b5950572 63
DavidGilesHitex 0:3331b5950572 64 /* 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) */
DavidGilesHitex 0:3331b5950572 65 /* as the device is quasi birectional */
DavidGilesHitex 0:3331b5950572 66 /* This is to avoid turning the pin from a designated input into an output by mistake */
DavidGilesHitex 0:3331b5950572 67 /* If the pin is designated as input and we have logic 1 on the input we and indvertantly write a 0 to it */
DavidGilesHitex 0:3331b5950572 68 /* then we will have a large current flow input the pin */
DavidGilesHitex 0:3331b5950572 69 /* Hence the 'or' block below prevents unwanted damage to the pin */
DavidGilesHitex 0:3331b5950572 70 /* Quasi direction is: 1 = input, 0 = output */
DavidGilesHitex 0:3331b5950572 71 port0_payload = (port0_payload | My_Local_Port0_Direction);
DavidGilesHitex 0:3331b5950572 72 port0_payload = (port1_payload | My_Local_Port1_Direction);
DavidGilesHitex 0:3331b5950572 73
DavidGilesHitex 0:3331b5950572 74 tx_array[ePCA9675_PORT0] = port0_payload; /* First is for Port 0 */
DavidGilesHitex 0:3331b5950572 75 tx_array[ePCA9675_PORT1] = port1_payload; /* Second is for Port 1 */
DavidGilesHitex 0:3331b5950572 76
DavidGilesHitex 0:3331b5950572 77 Ack_Status = My_Local_I2C -> write(My_Lcoal_Slave_Address << 1, tx_array, 2, eI2C_NO_REPEATED_START);
DavidGilesHitex 0:3331b5950572 78 return Ack_Status;
DavidGilesHitex 0:3331b5950572 79 }
DavidGilesHitex 0:3331b5950572 80
DavidGilesHitex 0:3331b5950572 81
DavidGilesHitex 0:3331b5950572 82 /* Read two bytes from the device */
DavidGilesHitex 0:3331b5950572 83 sint32_t PCA9675::read_data(uint8_t *read_port0, uint8_t *read_port1)
DavidGilesHitex 0:3331b5950572 84 {
DavidGilesHitex 0:3331b5950572 85 sint32_t Ack_Status = eI2C_ACK;
DavidGilesHitex 0:3331b5950572 86 sint8_t rx_array[2]; /* Local reception array */
DavidGilesHitex 0:3331b5950572 87
DavidGilesHitex 0:3331b5950572 88 Ack_Status = My_Local_I2C -> read(My_Lcoal_Slave_Address << 1, rx_array, 2, eI2C_NO_REPEATED_START);
DavidGilesHitex 0:3331b5950572 89
DavidGilesHitex 0:3331b5950572 90 *read_port0 = rx_array[ePCA9675_PORT0]; /* transfer data back to pointer */
DavidGilesHitex 0:3331b5950572 91 *read_port1 = rx_array[ePCA9675_PORT1]; /* transfer data back to pointer */
DavidGilesHitex 0:3331b5950572 92 return Ack_Status;
DavidGilesHitex 0:3331b5950572 93 }
DavidGilesHitex 0:3331b5950572 94
DavidGilesHitex 0:3331b5950572 95
DavidGilesHitex 0:3331b5950572 96 /* Read the device ID */
DavidGilesHitex 0:3331b5950572 97 sint32_t PCA9675::read_device_ID(uint8_t *manufacturer, uint16_t *part_ident, uint8_t *die_revision)
DavidGilesHitex 0:3331b5950572 98
DavidGilesHitex 0:3331b5950572 99 {
DavidGilesHitex 0:3331b5950572 100 sint32_t Ack_Status = eI2C_ACK;
DavidGilesHitex 0:3331b5950572 101 sint8_t rx_array[3] = {0,0,0};
DavidGilesHitex 0:3331b5950572 102 uint32_t temp_value = 0;
DavidGilesHitex 0:3331b5950572 103 sint8_t tx_array = (My_Lcoal_Slave_Address << 1);
DavidGilesHitex 0:3331b5950572 104
DavidGilesHitex 0:3331b5950572 105
DavidGilesHitex 0:3331b5950572 106 Ack_Status = My_Local_I2C -> write(0xF8, &tx_array, 1, eI2C_REPEATED_START);
DavidGilesHitex 0:3331b5950572 107 Ack_Status = My_Local_I2C -> read(0xF9, rx_array, 3, eI2C_NO_REPEATED_START);
DavidGilesHitex 0:3331b5950572 108
DavidGilesHitex 0:3331b5950572 109 temp_value = rx_array[0];
DavidGilesHitex 0:3331b5950572 110 temp_value = (temp_value << 8);
DavidGilesHitex 0:3331b5950572 111
DavidGilesHitex 0:3331b5950572 112 temp_value = (temp_value | rx_array[1]);
DavidGilesHitex 0:3331b5950572 113 temp_value = (temp_value << 8);
DavidGilesHitex 0:3331b5950572 114
DavidGilesHitex 0:3331b5950572 115 temp_value = (temp_value | rx_array[2]);
DavidGilesHitex 0:3331b5950572 116
DavidGilesHitex 0:3331b5950572 117
DavidGilesHitex 0:3331b5950572 118 *die_revision = (uint8_t) (temp_value & 0x00000003); /* 3 LSB bits are die revision */
DavidGilesHitex 0:3331b5950572 119 temp_value = (temp_value >> 3);
DavidGilesHitex 0:3331b5950572 120
DavidGilesHitex 0:3331b5950572 121 *part_ident = (uint16_t) (temp_value & 0x00001FFF); /* Next 13 bits are part identification */
DavidGilesHitex 0:3331b5950572 122 temp_value = (temp_value >> 13);
DavidGilesHitex 0:3331b5950572 123
DavidGilesHitex 0:3331b5950572 124 *manufacturer = (uint8_t) (temp_value & 0x000000FF); /* Next 8 bits are manufacturers name */
DavidGilesHitex 0:3331b5950572 125
DavidGilesHitex 0:3331b5950572 126 return Ack_Status;
DavidGilesHitex 0:3331b5950572 127 }
DavidGilesHitex 0:3331b5950572 128
DavidGilesHitex 0:3331b5950572 129
DavidGilesHitex 0:3331b5950572 130
DavidGilesHitex 0:3331b5950572 131
DavidGilesHitex 0:3331b5950572 132 /* Read the configured slave address */
DavidGilesHitex 0:3331b5950572 133 uint8_t PCA9675::read_slave_address()
DavidGilesHitex 0:3331b5950572 134 {
DavidGilesHitex 0:3331b5950572 135 return My_Lcoal_Slave_Address;
DavidGilesHitex 0:3331b5950572 136 }
DavidGilesHitex 0:3331b5950572 137
DavidGilesHitex 0:3331b5950572 138
DavidGilesHitex 0:3331b5950572 139