Pin manager support for sharing multipin buses.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "pin_manager.h"
|
||||
#include "wled.h"
|
||||
|
||||
#ifdef WLED_DEBUG
|
||||
static void DebugPrintOwnerTag(PinOwner tag)
|
||||
{
|
||||
uint32_t q = static_cast<uint8_t>(tag);
|
||||
@@ -10,6 +11,7 @@ static void DebugPrintOwnerTag(PinOwner tag)
|
||||
DEBUG_PRINT(F("(no owner)"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Actual allocation/deallocation routines
|
||||
bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag)
|
||||
@@ -19,12 +21,14 @@ bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag)
|
||||
|
||||
// if a non-zero ownerTag, only allow de-allocation if the owner's tag is provided
|
||||
if ((ownerTag[gpio] != PinOwner::None) && (ownerTag[gpio] != tag)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN DEALLOC: IO "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" allocated by "));
|
||||
DebugPrintOwnerTag(ownerTag[gpio]);
|
||||
DEBUG_PRINT(F(", but attempted de-allocation by "));
|
||||
DebugPrintOwnerTag(tag);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -34,6 +38,49 @@ bool PinManagerClass::deallocatePin(byte gpio, PinOwner tag)
|
||||
ownerTag[gpio] = PinOwner::None;
|
||||
return true;
|
||||
}
|
||||
|
||||
// support function for deallocating multiple pins
|
||||
bool PinManagerClass::deallocateMultiplePins(const uint8_t *pinArray, byte arrayElementCount, PinOwner tag)
|
||||
{
|
||||
bool shouldFail = false;
|
||||
DEBUG_PRINTLN(F("MULTIPIN DEALLOC"));
|
||||
// first verify the pins are OK and allocated by selected owner
|
||||
for (int i = 0; i < arrayElementCount; i++) {
|
||||
byte gpio = pinArray[i];
|
||||
if (gpio == 0xFF) {
|
||||
// explicit support for io -1 as a no-op (no allocation of pin),
|
||||
// as this can greatly simplify configuration arrays
|
||||
continue;
|
||||
}
|
||||
if (isPinAllocated(gpio, tag)) {
|
||||
// if the current pin is allocated by selected owner it is possible to release it
|
||||
continue;
|
||||
}
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN DEALLOC: IO "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" allocated by "));
|
||||
DebugPrintOwnerTag(ownerTag[gpio]);
|
||||
DEBUG_PRINT(F(", but attempted de-allocation by "));
|
||||
DebugPrintOwnerTag(tag);
|
||||
#endif
|
||||
shouldFail = true;
|
||||
}
|
||||
if (shouldFail) {
|
||||
return false; // no pins deallocated
|
||||
}
|
||||
if (tag==PinOwner::HW_I2C) {
|
||||
if (i2cAllocCount && --i2cAllocCount>0) {
|
||||
// no deallocation done until last owner releases pins
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < arrayElementCount; i++) {
|
||||
deallocatePin(pinArray[i], tag);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag)
|
||||
{
|
||||
bool shouldFail = false;
|
||||
@@ -46,17 +93,24 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
continue;
|
||||
}
|
||||
if (!isPinOk(gpio, mptArray[i].isOutput)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: Invalid pin attempted to be allocated: "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINTLN(F(""));
|
||||
#endif
|
||||
shouldFail = true;
|
||||
}
|
||||
if (isPinAllocated(gpio)) {
|
||||
if (tag==PinOwner::HW_I2C && isPinAllocated(gpio, tag)) {
|
||||
// allow multiple "allocations" of HW I2C bus pins
|
||||
continue;
|
||||
} else if (isPinAllocated(gpio)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: FAIL: IO "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" already allocated by "));
|
||||
DebugPrintOwnerTag(ownerTag[gpio]);
|
||||
DEBUG_PRINTLN(F(""));
|
||||
#endif
|
||||
shouldFail = true;
|
||||
}
|
||||
}
|
||||
@@ -64,6 +118,8 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tag==PinOwner::HW_I2C) i2cAllocCount++;
|
||||
|
||||
// all pins are available .. track each one
|
||||
for (int i = 0; i < arrayElementCount; i++) {
|
||||
byte gpio = mptArray[i].pin;
|
||||
@@ -79,15 +135,19 @@ bool PinManagerClass::allocateMultiplePins(const managed_pin_type * mptArray, by
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PinManagerClass::allocatePin(byte gpio, bool output, PinOwner tag)
|
||||
{
|
||||
if (!isPinOk(gpio, output)) return false;
|
||||
// HW I2C pins have to be allocated using allocateMultiplePins variant since there is always SCL/SDA pair
|
||||
if (!isPinOk(gpio, output) || tag==PinOwner::HW_I2C) return false;
|
||||
if (isPinAllocated(gpio)) {
|
||||
#ifdef WLED_DEBUG
|
||||
DEBUG_PRINT(F("PIN ALLOC: Pin "));
|
||||
DEBUG_PRINT(gpio);
|
||||
DEBUG_PRINT(F(" already allocated by "));
|
||||
DebugPrintOwnerTag(ownerTag[gpio]);
|
||||
DEBUG_PRINTLN(F(""));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -106,7 +166,7 @@ bool PinManagerClass::isPinAllocated(byte gpio, PinOwner tag)
|
||||
if (!isPinOk(gpio, false)) return true;
|
||||
if ((tag != PinOwner::None) && (ownerTag[gpio] != tag)) return false;
|
||||
byte by = gpio >> 3;
|
||||
byte bi = gpio - 8*by;
|
||||
byte bi = gpio - (by<<3);
|
||||
return bitRead(pinAlloc[by], bi);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user