Complete PCF8574 and PCF74A library with interrupt handling
Dependents: Nucleo_PCF8574_led_iic Dawson_Controller
PCF8574.cpp
- Committer:
- bborredon
- Date:
- 2012-07-14
- Revision:
- 0:6d75da25c179
File content as of revision 0:6d75da25c179:
/*********************************************************** Author: Bernard Borredon Date: 27 december 2011 Version: 1.0 ************************************************************/ #include "PCF8574.h" // Local object address static PCF8574 *pt_pcf8574; // User callback function address static void (*_ptf)(uint8_t data,PCF8574 *o)= NULL; // Callback static void _InterruptCB(void) { uint8_t data = 0; bitset<8> data_p,val; bitset<8> changed; uint8_t i; // Read PCF8574 port (to acknowledge interrupt) data = pt_pcf8574->read(); // Set bits that have changed pt_pcf8574->getIntrData(data_p,changed); changed = 0; val = data; for(i = 0;i < 8;i++) { if(val[i] != data_p[i]) changed[i] = 1; } pt_pcf8574->setIntrData(val,changed); // Call user callback, if any with port value if(_ptf != NULL) _ptf(data,pt_pcf8574); } // Constructor PCF8574::PCF8574(PinName sda,PinName scl,uint8_t address, bool typeA) : _i2c(sda, scl) { _errnum = PCF8574_NoError; _intr = NULL; pt_pcf8574 = NULL; _intr_data = 0xFF; _intr_bits_changed = 0; _intr_flag = 0; // Set the address if(typeA) { // PCF8574A _PCF8574_address = 0x70; } else { // PCF8574 _PCF8574_address = 0x40; } _address = address; // Check address validity (between 0 and 7) if(address > 7) { _errnum = PCF8574_BadAddress; } // Shift address _address = _address << 1; // Set I2C frequency (100 MHz) _i2c.frequency(100000); } // Read IO port uint8_t PCF8574::read(void) { uint8_t data; int ack; // Check error if(_errnum) return(0); // No error _errnum = PCF8574_NoError; // Read port ack = _i2c.read(_PCF8574_address | _address,(char *)&data,sizeof(data)); // Check error if(ack != 0) { _errnum = PCF8574_I2cError; } return(data); } // Write IO port void PCF8574::write(uint8_t data) { int ack; // Check error if(_errnum) return; // No error _errnum = PCF8574_NoError; // Write port ack = _i2c.write(_PCF8574_address | _address,(char *)&data,sizeof(data)); // Check error if(ack != 0) { _errnum = PCF8574_I2cError; } } // Write IO pin void PCF8574::write(uint8_t pin, uint8_t value) { uint8_t data; // Read IO port value data = read(); // Change bit pin if(value) BIT_SET(data,pin); else BIT_CLEAR(data,pin); // Write new IO port data write(data); } // Write to IO pins with a bitset and a bitset mask void PCF8574::write(bitset<8> data, bitset<8> mask) { uint8_t i; bitset<8> nd; nd = (bitset<8>) read(); for(i = 0;i < 8;i++) { if(mask[i]) nd[i] = data[i]; } write((uint8_t) nd.to_ulong()); } // Set pin and callback interrupt void PCF8574::interrupt(PinName intr,void (*ftpr)(uint8_t, PCF8574 *)) { // Check error if(_errnum) return; // No error _errnum = PCF8574_NoError; // Create InterruptIn instance if needed if(_intr == NULL) { _intr = new InterruptIn(intr); // Set InterruptIn callback if(_intr != NULL) _intr->fall(_InterruptCB); else _errnum = PCF8574_IntrError; } _ptf = ftpr; // User callback address pt_pcf8574 = this; // Object instance _intr_data = read(); // IO port value _intr_flag = 1; // Function called } // Get current error number uint8_t PCF8574::getError(void) { return(_errnum); } // Memorize IO port value and bits that have changed when interrupt void PCF8574::setIntrData(bitset<8> data, bitset<8> changed) { _intr_data = data; _intr_bits_changed = changed; } // Get IO port value and bits that have changed when interrupt void PCF8574::getIntrData(bitset<8>& data, bitset<8>& changed) { data = _intr_data; changed = _intr_bits_changed; } // Redefine () operator PCF8574::operator uint8_t() { return read(); } // Redefine = operator PCF8574 &PCF8574::operator=(uint8_t data) { write((int)data); return(*this); }