From a3a2eff603f31e63ad6b1154572b8138d4fd8edb Mon Sep 17 00:00:00 2001 From: Renzo Mischianti Date: Tue, 30 Apr 2024 17:12:42 +0200 Subject: [PATCH] Manage INPUT_PULLUP, LOW latency mode, support Arduino UNO R4 and initial OUTPUT value --- PCF8575.cpp | 447 +++++++++++++++++++++++++++++++-------------- PCF8575.h | 25 ++- README.md | 1 + library.json | 2 +- library.properties | 2 +- 5 files changed, 337 insertions(+), 140 deletions(-) diff --git a/PCF8575.cpp b/PCF8575.cpp index bac65f8..6cfb6ff 100644 --- a/PCF8575.cpp +++ b/PCF8575.cpp @@ -159,6 +159,33 @@ bool PCF8575::begin(uint8_t address){ return PCF8575::begin(); } +void PCF8575::attachInterrupt(){ + // If using interrupt set interrupt value to pin + if (_usingInterrupt){ +// for (int i = 0; i < 8;i++){ +// if (encoderPins[i]) PCF8574::digitalRead(i); +// } +// PCF8574::digitalReadAll(); +// (*_interruptFunction)(); + +// DEBUG_PRINTLN("Using interrupt pin (not all pin is interrupted)"); +// ::pinMode(_interruptPin, INPUT_PULLUP); +// attachInterrupt(digitalPinToInterrupt(_interruptPin), (*_interruptFunction), FALLING ); + DEBUG_PRINTLN("Using interrupt pin (not all pin is interrupted)"); + ::pinMode(_interruptPin, INPUT_PULLUP); + ::attachInterrupt(digitalPinToInterrupt(_interruptPin), (*_interruptFunction), FALLING ); + } + +} +void PCF8575::detachInterrupt(){ + // If using interrupt set interrupt value to pin + if (_usingInterrupt){ + ::detachInterrupt(digitalPinToInterrupt(_interruptPin)); + DEBUG_PRINTLN("Detach interrupt pin"); + } + +} + /** * wake up i2c controller @@ -185,34 +212,40 @@ bool PCF8575::begin(){ _wire->begin(); #endif -// Serial.println( writeMode, BIN); -// Serial.println( readMode, BIN); +// Check if there are pins to set low +if (writeMode>0 || readMode>0){ + DEBUG_PRINTLN("Set write mode"); + _wire->beginTransmission(_address); - // Check if there are pins to set low - if (writeMode>0 || readMode>0){ - DEBUG_PRINTLN("Set write mode"); - _wire->beginTransmission(_address); - DEBUG_PRINT(" "); - DEBUG_PRINT("usedPin pin "); + DEBUG_PRINT("resetInitial pin "); +#ifdef PCF8575_SOFT_INITIALIZATION + resetInitial = writeModeUp | readModePullUp; +#else + resetInitial = writeModeUp | readMode; +#endif + DEBUG_PRINTLN( resetInitial, BIN); - uint16_t usedPin = writeMode | readMode; - DEBUG_PRINTLN( ~usedPin, BIN); -// Serial.println( ~usedPin, BIN); +// _wire->write(resetInitial); + _wire->write((uint8_t) resetInitial); + _wire->write((uint8_t) (resetInitial >> 8)); - _wire->write((uint8_t) ~usedPin); - _wire->write((uint8_t) (~(usedPin >> 8))); + initialBuffer = writeModeUp | readModePullUp; + byteBuffered = initialBuffer; + writeByteBuffered = writeModeUp; - DEBUG_PRINTLN("Start end trasmission if stop here check pullup resistor."); - this->transmissionStatus = _wire->endTransmission(); - } + DEBUG_PRINTLN("Start end trasmission if stop here check pullup resistor."); + this->transmissionStatus = _wire->endTransmission(); +} // If using interrupt set interrupt value to pin - if (_usingInterrupt){ - DEBUG_PRINTLN("Using interrupt pin (not all pin is interrupted)"); - ::pinMode(_interruptPin, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(_interruptPin), (*_interruptFunction), FALLING ); - } +// if (_usingInterrupt){ +// DEBUG_PRINTLN("Using interrupt pin (not all pin is interrupted)"); +// ::pinMode(_interruptPin, INPUT_PULLUP); +// ::attachInterrupt(digitalPinToInterrupt(_interruptPin), (*_interruptFunction), FALLING ); +// } + + PCF8575::attachInterrupt(); // inizialize last read lastReadMillis = millis(); @@ -225,7 +258,7 @@ bool PCF8575::begin(){ * @param pin: pin to set * @param mode: mode, supported only INPUT or OUTPUT (to semplify) */ -void PCF8575::pinMode(uint8_t pin, uint8_t mode){ +void PCF8575::pinMode(uint8_t pin, uint8_t mode, uint8_t output_start){ DEBUG_PRINT("Set pin "); DEBUG_PRINT(pin); DEBUG_PRINT(" as "); @@ -233,19 +266,57 @@ void PCF8575::pinMode(uint8_t pin, uint8_t mode){ if (mode == OUTPUT){ writeMode = writeMode | bit(pin); + if (output_start==HIGH) { + writeModeUp = writeModeUp | bit(pin); + } + + //writeMode = writeMode | bit(pin); readMode = readMode & ~bit(pin); -// DEBUG_PRINT("writeMode: "); -// DEBUG_PRINT(writeMode, BIN); -// DEBUG_PRINT("readMode: "); -// DEBUG_PRINTLN(readMode, BIN); + readModePullDown = readModePullDown & ~bit(pin); + readModePullUp = readModePullUp & ~bit(pin); + + DEBUG_PRINT("W: "); + DEBUG_PRINT(writeMode, BIN); + DEBUG_PRINT(" R ALL: "); + DEBUG_PRINT(readMode, BIN); + + DEBUG_PRINT(" R Down: "); + DEBUG_PRINT(readModePullDown, BIN); + DEBUG_PRINT("R Up: "); + DEBUG_PRINTLN(readModePullUp, BIN); }else if (mode == INPUT){ writeMode = writeMode & ~bit(pin); - readMode = readMode | bit(pin); -// DEBUG_PRINT("writeMode: "); -// DEBUG_PRINT(writeMode, BIN); -// DEBUG_PRINT("readMode: "); -// DEBUG_PRINTLN(readMode, BIN); + + readMode = readMode | bit(pin); + readModePullDown = readModePullDown | bit(pin); + readModePullUp = readModePullUp & ~bit(pin); + + DEBUG_PRINT("W: "); + DEBUG_PRINT(writeMode, BIN); + DEBUG_PRINT(" R ALL: "); + DEBUG_PRINT(readMode, BIN); + + DEBUG_PRINT(" R Down: "); + DEBUG_PRINT(readModePullDown, BIN); + DEBUG_PRINT("R Up: "); + DEBUG_PRINTLN(readModePullUp, BIN); + }else if (mode == INPUT_PULLUP){ + writeMode = writeMode & ~bit(pin); + + readMode = readMode | bit(pin); + readModePullDown = readModePullDown & ~bit(pin); + readModePullUp = readModePullUp | bit(pin); + + DEBUG_PRINT("W: "); + DEBUG_PRINT(writeMode, BIN); + DEBUG_PRINT(" R ALL: "); + DEBUG_PRINT(readMode, BIN); + + DEBUG_PRINT(" R Down: "); + DEBUG_PRINT(readModePullDown, BIN); + DEBUG_PRINT("R Up: "); + DEBUG_PRINTLN(readModePullUp, BIN); } else{ DEBUG_PRINTLN("Mode non supported by PCF8575") @@ -260,15 +331,15 @@ void PCF8575::pinMode(uint8_t pin, uint8_t mode){ * @param force */ void PCF8575::readBuffer(bool force){ - if (millis() > PCF8575::lastReadMillis+READ_ELAPSED_TIME || _usingInterrupt || force){ + if (millis() > PCF8575::lastReadMillis+latency || _usingInterrupt || force){ _wire->requestFrom(_address,(uint8_t)2);// Begin transmission to PCF8575 with the buttons lastReadMillis = millis(); if(_wire->available()) // If uint16_ts are available to be recieved { uint16_t iInput = _wire->read();// Read a uint16_t iInput |= _wire->read() << 8;// Read a uint16_t - if ((iInput & readMode)>0){ - byteBuffered = byteBuffered | (uint16_t)iInput; + if ((iInput & readModePullDown)>0 and (~iInput & readModePullUp)>0){ + byteBuffered = (byteBuffered & ~readMode) | (uint16_t)iInput; } } } @@ -290,14 +361,19 @@ void PCF8575::readBuffer(bool force){ uint16_t iInput = _wire->read();// Read a uint16_t iInput |= _wire->read() << 8;// Read a uint16_t - if ((iInput & readMode)>0){ - DEBUG_PRINT("Input "); - DEBUG_PRINTLN((uint16_t)iInput, BIN); + if ((readModePullDown & iInput)>0 or (readModePullUp & ~iInput)>0){ + DEBUG_PRINT(" -------- CHANGE --------- "); + byteBuffered = (byteBuffered & ~readMode) | (uint16_t)iInput; + } - byteBuffered = byteBuffered | (uint16_t)iInput; - DEBUG_PRINT("byteBuffered "); - DEBUG_PRINTLN(byteBuffered, BIN); - } +// if ((iInput & readMode)>0){ +// DEBUG_PRINT("Input "); +// DEBUG_PRINTLN((uint16_t)iInput, BIN); +// +// byteBuffered = byteBuffered | (uint16_t)iInput; +// DEBUG_PRINT("byteBuffered "); +// DEBUG_PRINTLN(byteBuffered, BIN); +// } } DEBUG_PRINT("Buffer value "); @@ -319,6 +395,24 @@ void PCF8575::readBuffer(bool force){ if ((bit(13) & readMode)>0) digitalInput.p15 = ((byteBuffered & bit(13))>0)?HIGH:LOW; if ((bit(14) & readMode)>0) digitalInput.p16 = ((byteBuffered & bit(14))>0)?HIGH:LOW; if ((bit(15) & readMode)>0) digitalInput.p17 = ((byteBuffered & bit(15))>0)?HIGH:LOW; + + if ((bit(0) & writeMode)>0) digitalInput.p0 = ((writeByteBuffered & bit(0))>0)?HIGH:LOW; + if ((bit(1) & writeMode)>0) digitalInput.p1 = ((writeByteBuffered & bit(1))>0)?HIGH:LOW; + if ((bit(2) & writeMode)>0) digitalInput.p2 = ((writeByteBuffered & bit(2))>0)?HIGH:LOW; + if ((bit(3) & writeMode)>0) digitalInput.p3 = ((writeByteBuffered & bit(3))>0)?HIGH:LOW; + if ((bit(4) & writeMode)>0) digitalInput.p4 = ((writeByteBuffered & bit(4))>0)?HIGH:LOW; + if ((bit(5) & writeMode)>0) digitalInput.p5 = ((writeByteBuffered & bit(5))>0)?HIGH:LOW; + if ((bit(6) & writeMode)>0) digitalInput.p6 = ((writeByteBuffered & bit(6))>0)?HIGH:LOW; + if ((bit(7) & writeMode)>0) digitalInput.p7 = ((writeByteBuffered & bit(7))>0)?HIGH:LOW; + if ((bit(8) & writeMode)>0) digitalInput.p10 = ((writeByteBuffered & bit(8))>0)?HIGH:LOW; + if ((bit(9) & writeMode)>0) digitalInput.p11 = ((writeByteBuffered & bit(9))>0)?HIGH:LOW; + if ((bit(10) & writeMode)>0) digitalInput.p12 = ((writeByteBuffered & bit(10))>0)?HIGH:LOW; + if ((bit(11) & writeMode)>0) digitalInput.p13 = ((writeByteBuffered & bit(11))>0)?HIGH:LOW; + if ((bit(12) & writeMode)>0) digitalInput.p14 = ((writeByteBuffered & bit(12))>0)?HIGH:LOW; + if ((bit(13) & writeMode)>0) digitalInput.p15 = ((writeByteBuffered & bit(13))>0)?HIGH:LOW; + if ((bit(14) & writeMode)>0) digitalInput.p16 = ((writeByteBuffered & bit(14))>0)?HIGH:LOW; + if ((bit(15) & writeMode)>0) digitalInput.p17 = ((writeByteBuffered & bit(15))>0)?HIGH:LOW; + #else if ((bit(0) & readMode)>0) digitalInput.p0 = ((byteBuffered & bit(0))>0)?HIGH:LOW; if ((bit(1) & readMode)>0) digitalInput.p1 = ((byteBuffered & bit(1))>0)?HIGH:LOW; @@ -336,12 +430,35 @@ void PCF8575::readBuffer(bool force){ if ((bit(13) & readMode)>0) digitalInput.p13 = ((byteBuffered & bit(13))>0)?HIGH:LOW; if ((bit(14) & readMode)>0) digitalInput.p14 = ((byteBuffered & bit(14))>0)?HIGH:LOW; if ((bit(15) & readMode)>0) digitalInput.p15 = ((byteBuffered & bit(15))>0)?HIGH:LOW; + + if ((bit(0) & writeMode)>0) digitalInput.p0 = ((writeByteBuffered & bit(0))>0)?HIGH:LOW; + if ((bit(1) & writeMode)>0) digitalInput.p1 = ((writeByteBuffered & bit(1))>0)?HIGH:LOW; + if ((bit(2) & writeMode)>0) digitalInput.p2 = ((writeByteBuffered & bit(2))>0)?HIGH:LOW; + if ((bit(3) & writeMode)>0) digitalInput.p3 = ((writeByteBuffered & bit(3))>0)?HIGH:LOW; + if ((bit(4) & writeMode)>0) digitalInput.p4 = ((writeByteBuffered & bit(4))>0)?HIGH:LOW; + if ((bit(5) & writeMode)>0) digitalInput.p5 = ((writeByteBuffered & bit(5))>0)?HIGH:LOW; + if ((bit(6) & writeMode)>0) digitalInput.p6 = ((writeByteBuffered & bit(6))>0)?HIGH:LOW; + if ((bit(7) & writeMode)>0) digitalInput.p7 = ((writeByteBuffered & bit(7))>0)?HIGH:LOW; + if ((bit(8) & writeMode)>0) digitalInput.p8 = ((writeByteBuffered & bit(8))>0)?HIGH:LOW; + if ((bit(9) & writeMode)>0) digitalInput.p9 = ((writeByteBuffered & bit(9))>0)?HIGH:LOW; + if ((bit(10) & writeMode)>0) digitalInput.p10 = ((writeByteBuffered & bit(10))>0)?HIGH:LOW; + if ((bit(11) & writeMode)>0) digitalInput.p11 = ((writeByteBuffered & bit(11))>0)?HIGH:LOW; + if ((bit(12) & writeMode)>0) digitalInput.p12 = ((writeByteBuffered & bit(12))>0)?HIGH:LOW; + if ((bit(13) & writeMode)>0) digitalInput.p13 = ((writeByteBuffered & bit(13))>0)?HIGH:LOW; + if ((bit(14) & writeMode)>0) digitalInput.p14 = ((writeByteBuffered & bit(14))>0)?HIGH:LOW; + if ((bit(15) & writeMode)>0) digitalInput.p15 = ((writeByteBuffered & bit(15))>0)?HIGH:LOW; + #endif - if ((readMode & byteBuffered)>0){ - byteBuffered = ~readMode & byteBuffered; +// if ((readMode & byteBuffered)>0){ +// byteBuffered = ~readMode & byteBuffered; +// DEBUG_PRINT("Buffer hight value readed set readed "); +// DEBUG_PRINTLN(byteBuffered, BIN); +// } + byteBuffered = (initialBuffer & readMode) | (byteBuffered & ~readMode); //~readMode & byteBuffered; + DEBUG_PRINT("Buffer hight value readed set readed "); DEBUG_PRINTLN(byteBuffered, BIN); - } + DEBUG_PRINT("Return value "); return digitalInput; }; @@ -361,26 +478,40 @@ void PCF8575::readBuffer(bool force){ uint16_t iInput = _wire->read();// Read a uint16_t iInput |= _wire->read() << 8;// Read a uint16_t - if ((iInput & readMode)>0){ - DEBUG_PRINT("Input "); - DEBUG_PRINTLN((uint16_t)iInput, BIN); +// if ((iInput & readMode)>0){ +// DEBUG_PRINT("Input "); +// DEBUG_PRINTLN((uint16_t)iInput, BIN); +// +// byteBuffered = byteBuffered | (uint16_t)iInput; +// DEBUG_PRINT("byteBuffered "); +// DEBUG_PRINTLN(byteBuffered, BIN); +// } + if ((readModePullDown & iInput)>0 or (readModePullUp & ~iInput)>0){ + DEBUG_PRINT(" -------- CHANGE --------- "); + byteBuffered = (byteBuffered & ~readMode) | (uint16_t)iInput; - byteBuffered = byteBuffered | (uint16_t)iInput; - DEBUG_PRINT("byteBuffered "); - DEBUG_PRINTLN(byteBuffered, BIN); } + } DEBUG_PRINT("Buffer value "); DEBUG_PRINTLN(byteBuffered, BIN); - uint16_t byteRead = byteBuffered; - - if ((readMode & byteBuffered)>0){ - byteBuffered = ~readMode & byteBuffered; +// uint16_t byteRead = byteBuffered; +// +// if ((readMode & byteBuffered)>0){ +// byteBuffered = ~readMode & byteBuffered; +// DEBUG_PRINT("Buffer hight value readed set readed "); +// DEBUG_PRINTLN(byteBuffered, BIN); +// } + byte byteRead = byteBuffered | writeByteBuffered; + + //if ((byteBuffered & readModePullDown)>0 and (~byteBuffered & readModePullUp)>0){ +// byteBuffered = (resetInitial & readMode) | (byteBuffered & ~readMode); //~readMode & byteBuffered; + byteBuffered = (initialBuffer & readMode) | (byteBuffered & ~readMode); //~readMode & byteBuffered; DEBUG_PRINT("Buffer hight value readed set readed "); DEBUG_PRINTLN(byteBuffered, BIN); - } + DEBUG_PRINT("Return value "); return byteRead; }; @@ -392,105 +523,153 @@ void PCF8575::readBuffer(bool force){ * @param pin * @return */ -uint8_t PCF8575::digitalRead(uint8_t pin){ - uint8_t value = LOW; - if ((bit(pin) & writeMode)>0){ - DEBUG_PRINTLN("Pin in write mode, return value"); - DEBUG_PRINT("Write data "); - DEBUG_PRINT(writeByteBuffered, BIN); - DEBUG_PRINT(" for pin "); - DEBUG_PRINT(pin); - DEBUG_PRINT(" bin value "); - DEBUG_PRINT(bit(pin), BIN); - DEBUG_PRINT(" value "); - DEBUG_PRINTLN(value); - - if ((bit(pin) & writeByteBuffered)>0){ - value = HIGH; - }else{ - value = LOW; - } - return value; - } - - DEBUG_PRINT("Read pin "); - DEBUG_PRINTLN(pin); - // Check if pin already HIGH than read and prevent reread of i2c - if ((bit(pin) & byteBuffered)>0){ - DEBUG_PRINTLN("Pin already up"); - value = HIGH; - }else if ((/*(bit(pin) & byteBuffered)<=0 && */millis() > PCF8575::lastReadMillis+READ_ELAPSED_TIME) /*|| _usingInterrupt*/){ - DEBUG_PRINTLN("Read from buffer"); - _wire->requestFrom(_address,(uint8_t)2);// Begin transmission to PCF8575 with the buttons - lastReadMillis = millis(); - if(_wire->available()) // If bytes are available to be recieved - { - DEBUG_PRINTLN("Data ready"); + uint8_t PCF8575::digitalRead(uint8_t pin, bool forceReadNow){ + uint8_t value = (bit(pin) & readModePullUp)?HIGH:LOW; + DEBUG_PRINT("Read pin "); + DEBUG_PRINT (pin); + // Check if pin already HIGH than read and prevent reread of i2c + // DEBUG_PRINTLN("----------------------------------") + // DEBUG_PRINT("readModePullUp "); + // DEBUG_PRINTLN(readModePullUp, BIN); + // DEBUG_PRINT("readModePullDown "); + // DEBUG_PRINTLN(readModePullDown, BIN); + // DEBUG_PRINT("byteBuffered "); + // DEBUG_PRINTLN(byteBuffered, BIN); + + + if ((((bit(pin) & (readModePullDown & byteBuffered))>0) or (bit(pin) & (readModePullUp & ~byteBuffered))>0 )){ + DEBUG_PRINTLN(" ...Pin already set"); + if ((bit(pin) & byteBuffered)>0){ + value = HIGH; + }else{ + value = LOW; + } + }else if (forceReadNow || (millis() > PCF8575::lastReadMillis+latency)){ + DEBUG_PRINT(" ...Read from buffer... "); + _wire->requestFrom(_address,(uint8_t)2);// Begin transmission to PCF8574 with the buttons + lastReadMillis = millis(); + if(_wire->available()) // If bytes are available to be recieved + { + DEBUG_PRINTLN(" Data ready"); uint16_t iInput = _wire->read();// Read a uint16_t iInput |= _wire->read() << 8;// Read a uint16_t - -// Serial.println(iInput, BIN); - - if ((iInput & readMode)>0){ DEBUG_PRINT("Input "); DEBUG_PRINTLN((uint16_t)iInput, BIN); - byteBuffered = byteBuffered | (uint16_t)iInput; - DEBUG_PRINT("byteBuffered "); - DEBUG_PRINTLN(byteBuffered, BIN); - - if ((bit(pin) & byteBuffered)>0){ - value = HIGH; + if ((readModePullDown & iInput)>0 or (readModePullUp & ~iInput)>0){ + DEBUG_PRINT(" -------- CHANGE --------- "); + byteBuffered = (byteBuffered & ~readMode) | (uint16_t)iInput; + if ((bit(pin) & byteBuffered)>0){ + value = HIGH; + }else{ + value = LOW; + } + // value = (bit(pin) & byteBuffered); } } - } - } - DEBUG_PRINT("Buffer value "); - DEBUG_PRINTLN(byteBuffered, BIN); - // If HIGH set to low to read buffer only one time - if (value==HIGH){ - byteBuffered = ~bit(pin) & byteBuffered; - DEBUG_PRINT("Buffer hight value readed set readed "); - DEBUG_PRINTLN(byteBuffered, BIN); - } - DEBUG_PRINT("Return value "); - DEBUG_PRINTLN(value); - return value; -}; - + } + DEBUG_PRINT(" ..Buffer value "); + DEBUG_PRINT(byteBuffered, BIN); + // If HIGH set to low to read buffer only one time + if ((bit(pin) & readModePullDown) and value==HIGH){ + byteBuffered = bit(pin) ^ byteBuffered; + DEBUG_PRINT(" ...Buffer hight value readed set readed "); + DEBUG_PRINT (byteBuffered, BIN); + }else if ((bit(pin) & readModePullUp) and value==LOW){ + byteBuffered = bit(pin) ^ byteBuffered; + DEBUG_PRINT(" ...Buffer low value readed set readed "); + DEBUG_PRINT(byteBuffered, BIN); + }else if(bit(pin) & writeByteBuffered){ + value = HIGH; + } + DEBUG_PRINT(" ...Return value "); + DEBUG_PRINTLN(value); + return value; + }; /** * Write on pin * @param pin * @param value */ -void PCF8575::digitalWrite(uint8_t pin, uint8_t value){ +//void PCF8575::digitalWrite(uint8_t pin, uint8_t value){ +// DEBUG_PRINTLN("Begin trasmission"); +// _wire->beginTransmission(_address); //Begin the transmission to PCF8575 +// if (value==HIGH){ +// writeByteBuffered = writeByteBuffered | bit(pin); +// }else{ +// writeByteBuffered = writeByteBuffered & ~bit(pin); +// } +//// DEBUG_PRINT("Write data "); +//// DEBUG_PRINT(writeByteBuffered, BIN); +//// DEBUG_PRINT(" for pin "); +//// DEBUG_PRINT(pin); +//// DEBUG_PRINT(" bin value "); +//// DEBUG_PRINT(bit(pin), BIN); +//// DEBUG_PRINT(" value "); +//// DEBUG_PRINTLN(value); +// +//// Serial.print(" --> "); +//// Serial.println(writeByteBuffered); +//// Serial.println((uint8_t) writeByteBuffered); +//// Serial.println((uint8_t) (writeByteBuffered >> 8)); +// +// writeByteBuffered = writeByteBuffered & writeMode; +// _wire->write((uint8_t) writeByteBuffered); +// _wire->write((uint8_t) (writeByteBuffered >> 8)); +// DEBUG_PRINTLN("Start end trasmission if stop here check pullup resistor."); +// +// _wire->endTransmission(); +//}; + +bool PCF8575::digitalWrite(uint8_t pin, uint8_t value){ DEBUG_PRINTLN("Begin trasmission"); - _wire->beginTransmission(_address); //Begin the transmission to PCF8575 + _wire->beginTransmission(_address); //Begin the transmission to PCF8574 + DEBUG_PRINT("Value "); + DEBUG_PRINT(value); + DEBUG_PRINT(" Write data pre "); + DEBUG_PRINT(writeByteBuffered, BIN); + if (value==HIGH){ writeByteBuffered = writeByteBuffered | bit(pin); + byteBuffered = writeByteBuffered | bit(pin); }else{ writeByteBuffered = writeByteBuffered & ~bit(pin); + byteBuffered = writeByteBuffered & ~bit(pin); } -// DEBUG_PRINT("Write data "); -// DEBUG_PRINT(writeByteBuffered, BIN); -// DEBUG_PRINT(" for pin "); -// DEBUG_PRINT(pin); -// DEBUG_PRINT(" bin value "); -// DEBUG_PRINT(bit(pin), BIN); -// DEBUG_PRINT(" value "); -// DEBUG_PRINTLN(value); - -// Serial.print(" --> "); -// Serial.println(writeByteBuffered); -// Serial.println((uint8_t) writeByteBuffered); -// Serial.println((uint8_t) (writeByteBuffered >> 8)); - - writeByteBuffered = writeByteBuffered & writeMode; - _wire->write((uint8_t) writeByteBuffered); - _wire->write((uint8_t) (writeByteBuffered >> 8)); + DEBUG_PRINT("Write data "); + DEBUG_PRINT(writeByteBuffered, BIN); + DEBUG_PRINT(" for pin "); + DEBUG_PRINT(pin); + DEBUG_PRINT(" bin value "); + DEBUG_PRINT(bit(pin), BIN); + DEBUG_PRINT(" value "); + DEBUG_PRINT(value); + + // writeByteBuffered = writeByteBuffered & (~writeMode & byteBuffered); + byteBuffered = (writeByteBuffered & writeMode) | (resetInitial & readMode); + + // byteBuffered = (writeByteBuffered & writeMode) | (byteBuffered & readMode); + DEBUG_PRINT(" byteBuffered "); + DEBUG_PRINTLN(byteBuffered, BIN); + + DEBUG_PRINT("Going to write data "); + DEBUG_PRINTLN(writeByteBuffered, BIN); + + _wire->write((uint8_t) byteBuffered); + _wire->write((uint8_t) (byteBuffered >> 8)); + +// _wire->write(byteBuffered); + + byteBuffered = (writeByteBuffered & writeMode) | (initialBuffer & readMode); + +// byteBuffered = (writeByteBuffered & writeMode) & (byteBuffered & readMode); DEBUG_PRINTLN("Start end trasmission if stop here check pullup resistor."); - _wire->endTransmission(); +// detachInterrupt(); + this->transmissionStatus = _wire->endTransmission(); +// attachInterrupt(); + + return this->isLastTransmissionSuccess(); }; diff --git a/PCF8575.h b/PCF8575.h index f1b8117..41bd00c 100644 --- a/PCF8575.h +++ b/PCF8575.h @@ -45,9 +45,14 @@ // Uncomment for low memory usage this prevent use of complex DigitalInput structure and free 7byte of memory // #define PCF8575_LOW_MEMORY +// Uncomment for low latency to get realtime data every time. +// #define PCF8575_LOW_LATENCY + // Define where debug output will be printed. #define DEBUG_PRINTER Serial +//#define PCF8575_SOFT_INITIALIZATION + // Define to manage original pinout of pcf8575 // like datasheet but not sequential //#define NOT_SEQUENTIAL_PINOUT @@ -61,7 +66,11 @@ #define DEBUG_PRINTLN(...) {} #endif -#define READ_ELAPSED_TIME 10 +#ifdef PCF8575_LOW_LATENCY + #define READ_ELAPSED_TIME 0 +#else + #define READ_ELAPSED_TIME 10 +#endif //#define P0 B00000001 //#define P1 B00000010 @@ -134,10 +143,10 @@ class PCF8575 { bool begin(); bool begin(uint8_t address); - void pinMode(uint8_t pin, uint8_t mode); + void pinMode(uint8_t pin, uint8_t mode, uint8_t output_start = HIGH); void readBuffer(bool force = true); - uint8_t digitalRead(uint8_t pin); + uint8_t digitalRead(uint8_t pin, bool forceReadNow = false); #ifndef PCF8575_LOW_MEMORY struct DigitalInput { #ifdef NOT_SEQUENTIAL_PINOUT @@ -182,12 +191,14 @@ class PCF8575 { #else uint16_t digitalReadAll(void); #endif - void digitalWrite(uint8_t pin, uint8_t value); + bool digitalWrite(uint8_t pin, uint8_t value); bool isLastTransmissionSuccess(){ DEBUG_PRINT(F("STATUS --> ")); DEBUG_PRINTLN(transmissionStatus); return transmissionStatus==0; } + void attachInterrupt(); + void detachInterrupt(); private: uint8_t _address; @@ -225,9 +236,15 @@ class PCF8575 { void (*_interruptFunction)(){}; uint16_t writeMode = 0; + uint16_t resetInitial = 0; + uint16_t initialBuffer = 0; + uint16_t writeModeUp = 0; uint16_t readMode = 0; + uint16_t readModePullUp = 0; + uint16_t readModePullDown = 0; uint16_t byteBuffered = 0; unsigned long lastReadMillis = 0; + int latency = READ_ELAPSED_TIME; uint16_t writeByteBuffered = 0; diff --git a/README.md b/README.md index f1a0878..1e685b6 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Library to use i2c analog IC with arduino and esp8266. Can read and write digital value with only 2 wire (perfect for ESP-01). + - 30/04/2024: v2.0.0 Manage INPUT_PULLUP, LOW latency mode, support Arduino UNO R4 and initial OUTPUT value - 01/02/2024: v1.1.2 Add the possibility to insert address at begin() function and return status of begin operation - 10/07/2023: v1.1.1 Add support for Arduino UNO R4 - 16/02/2023: v1.1.0 diff --git a/library.json b/library.json index 0faa36a..e961cc9 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "PCF8575 library", - "version": "1.1.2", + "version": "2.0.0", "keywords": "digital, i2c, encoder, expander, pcf8575, pcf8575a, esp32, esp8266, stm32, SAMD, Arduino, wire, Raspberry, rp2040", "description": "PCF8575 library. i2c digital expander for i2c digital expander for Arduino, Raspberry Pi Pico and rp2040 boards, esp32, SMT32 and ESP8266. Can read write digital values with only 2 wire. Very simple to use and encoder support.", "homepage": "https://www.mischianti.org/2019/07/22/pcf8575-i2c-16-bit-digital-i-o-expander/", diff --git a/library.properties b/library.properties index e3d2f16..d4d1be7 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=PCF8575 library -version=1.1.2 +version=2.0.0 author=Renzo Mischianti maintainer=Renzo Mischianti sentence=PCF8575, library for Arduino, Raspberry Pi Pico and rp2040 boards, esp32, SMT32 and ESP8266.