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.
Source/PCA9675.cpp
- Committer:
- DavidGilesHitex
- Date:
- 2010-11-23
- Revision:
- 0:3331b5950572
File content as of revision 0:3331b5950572:
/* 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; }