-
Notifications
You must be signed in to change notification settings - Fork 888
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into pr-fix4395
- Loading branch information
Showing
18 changed files
with
422 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#include "GpioLogic.h" | ||
#include <assert.h> | ||
|
||
void GpioVirtPin::set(bool value) | ||
{ | ||
if (value != this->value) { | ||
this->value = value ? PinState::On : PinState::Off; | ||
if (dependentPin) | ||
dependentPin->update(); | ||
} | ||
} | ||
|
||
GpioTransformer::GpioTransformer(GpioPin *outPin) : outPin(outPin) {} | ||
|
||
void GpioTransformer::set(bool value) | ||
{ | ||
outPin->set(value); | ||
} | ||
|
||
GpioNotTransformer::GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin) : GpioTransformer(outPin), inPin(inPin) | ||
{ | ||
assert(!inPin->dependentPin); // We only allow one dependent pin | ||
inPin->dependentPin = this; | ||
|
||
// Don't update at construction time, because various GpioPins might be global constructor based not yet initied because | ||
// order of operations for global constructors is not defined. | ||
// update(); | ||
} | ||
|
||
/** | ||
* Update the output pin based on the current state of the input pin. | ||
*/ | ||
void GpioNotTransformer::update() | ||
{ | ||
auto p = inPin->get(); | ||
if (p == GpioVirtPin::PinState::Unset) | ||
return; // Not yet fully initialized | ||
|
||
set(!p); | ||
} | ||
|
||
GpioBinaryTransformer::GpioBinaryTransformer(GpioVirtPin *inPin1, GpioVirtPin *inPin2, GpioPin *outPin, Operation operation) | ||
: GpioTransformer(outPin), inPin1(inPin1), inPin2(inPin2), operation(operation) | ||
{ | ||
assert(!inPin1->dependentPin); // We only allow one dependent pin | ||
inPin1->dependentPin = this; | ||
assert(!inPin2->dependentPin); // We only allow one dependent pin | ||
inPin2->dependentPin = this; | ||
|
||
// Don't update at construction time, because various GpioPins might be global constructor based not yet initied because | ||
// order of operations for global constructors is not defined. | ||
// update(); | ||
} | ||
|
||
void GpioBinaryTransformer::update() | ||
{ | ||
auto p1 = inPin1->get(), p2 = inPin2->get(); | ||
GpioVirtPin::PinState newValue = GpioVirtPin::PinState::Unset; | ||
|
||
if (p1 == GpioVirtPin::PinState::Unset) | ||
newValue = p2; // Not yet fully initialized | ||
else if (p2 == GpioVirtPin::PinState::Unset) | ||
newValue = p1; // Not yet fully initialized | ||
|
||
// If we've already found our value just use it, otherwise need to do the operation | ||
if (newValue == GpioVirtPin::PinState::Unset) { | ||
switch (operation) { | ||
case And: | ||
newValue = (GpioVirtPin::PinState)(p1 && p2); | ||
break; | ||
case Or: | ||
newValue = (GpioVirtPin::PinState)(p1 || p2); | ||
break; | ||
case Xor: | ||
newValue = (GpioVirtPin::PinState)(p1 != p2); | ||
break; | ||
default: | ||
assert(false); | ||
} | ||
} | ||
set(newValue); | ||
} | ||
|
||
GpioSplitter::GpioSplitter(GpioPin *outPin1, GpioPin *outPin2) : outPin1(outPin1), outPin2(outPin2) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
#pragma once | ||
|
||
#include "configuration.h" | ||
|
||
/**This is a set of classes to mediate access to GPIOs in a structured way. Most usage of GPIOs do not | ||
require these classes! But if your hardware has a GPIO that is 'shared' between multiple devices (i.e. a shared power enable) | ||
then using these classes might be able to let you cleanly turn on that enable when either dependent device is needed. | ||
Note: these classes are intended to be 99% inline for the common case so should have minimal impact on flash or RAM | ||
requirements. | ||
*/ | ||
|
||
/** | ||
* A logical GPIO pin (not necessary raw hardware). | ||
*/ | ||
class GpioPin | ||
{ | ||
public: | ||
virtual void set(bool value) = 0; | ||
}; | ||
|
||
/** | ||
* A physical GPIO hw pin. | ||
*/ | ||
class GpioHwPin : public GpioPin | ||
{ | ||
uint32_t num; | ||
|
||
public: | ||
explicit GpioHwPin(uint32_t num) : num(num) {} | ||
|
||
void set(bool value) { digitalWrite(num, value); } | ||
}; | ||
|
||
class GpioTransformer; | ||
class GpioNotTransformer; | ||
class GpioBinaryTransformer; | ||
|
||
/** | ||
* A virtual GPIO pin. | ||
*/ | ||
class GpioVirtPin : public GpioPin | ||
{ | ||
friend class GpioBinaryTransformer; | ||
friend class GpioNotTransformer; | ||
|
||
public: | ||
enum PinState { On = true, Off = false, Unset = 2 }; | ||
|
||
void set(bool value); | ||
PinState get() const { return value; } | ||
|
||
private: | ||
PinState value = PinState::Unset; | ||
GpioTransformer *dependentPin = NULL; | ||
}; | ||
|
||
#include <assert.h> | ||
|
||
/** | ||
* A 'smart' trigger that can depend in a fake GPIO and if that GPIO changes, drive some other downstream GPIO to change. | ||
* notably: the set method is not public (because it always is calculated by a subclass) | ||
*/ | ||
class GpioTransformer | ||
{ | ||
public: | ||
/** | ||
* Update the output pin based on the current state of the input pin. | ||
*/ | ||
virtual void update() = 0; | ||
|
||
protected: | ||
GpioTransformer(GpioPin *outPin); | ||
|
||
void set(bool value); | ||
|
||
private: | ||
GpioPin *outPin; | ||
}; | ||
|
||
/** | ||
* A transformer that performs a unary NOT operation from an input. | ||
*/ | ||
class GpioNotTransformer : public GpioTransformer | ||
{ | ||
public: | ||
GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin); | ||
|
||
protected: | ||
friend class GpioVirtPin; | ||
|
||
/** | ||
* Update the output pin based on the current state of the input pin. | ||
*/ | ||
void update(); | ||
|
||
private: | ||
GpioVirtPin *inPin; | ||
}; | ||
|
||
/** | ||
* A transformer that combines multiple virtual pins to drive an output pin | ||
*/ | ||
class GpioBinaryTransformer : public GpioTransformer | ||
{ | ||
|
||
public: | ||
enum Operation { And, Or, Xor }; | ||
|
||
GpioBinaryTransformer(GpioVirtPin *inPin1, GpioVirtPin *inPin2, GpioPin *outPin, Operation operation); | ||
|
||
protected: | ||
friend class GpioVirtPin; | ||
|
||
/** | ||
* Update the output pin based on the current state of the input pins. | ||
*/ | ||
void update(); | ||
|
||
private: | ||
GpioVirtPin *inPin1; | ||
GpioVirtPin *inPin2; | ||
Operation operation; | ||
}; | ||
|
||
/** | ||
* Sometimes a single output GPIO single needs to drive multiple physical GPIOs. This class provides that. | ||
*/ | ||
class GpioSplitter : public GpioPin | ||
{ | ||
|
||
public: | ||
GpioSplitter(GpioPin *outPin1, GpioPin *outPin2); | ||
|
||
void set(bool value) | ||
{ | ||
outPin1->set(value); | ||
outPin2->set(value); | ||
} | ||
|
||
private: | ||
GpioPin *outPin1; | ||
GpioPin *outPin2; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#include "Led.h" | ||
#include "PowerMon.h" | ||
#include "main.h" | ||
#include "power.h" | ||
|
||
GpioVirtPin ledForceOn, ledBlink; | ||
|
||
#if defined(LED_PIN) | ||
// Most boards have a GPIO for LED control | ||
static GpioHwPin ledRawHwPin(LED_PIN); | ||
#else | ||
static GpioVirtPin ledRawHwPin; // Dummy pin for no hardware | ||
#endif | ||
|
||
#if LED_STATE_ON == 0 | ||
static GpioVirtPin ledHwPin; | ||
static GpioNotTransformer ledInverter(&ledHwPin, &ledRawHwPin); | ||
#else | ||
static GpioPin &ledHwPin = ledRawHwPin; | ||
#endif | ||
|
||
#if defined(HAS_PMU) | ||
/** | ||
* A GPIO controlled by the PMU | ||
*/ | ||
class GpioPmuPin : public GpioPin | ||
{ | ||
public: | ||
void set(bool value) | ||
{ | ||
if (pmu_found && PMU) { | ||
// blink the axp led | ||
PMU->setChargingLedMode(value ? XPOWERS_CHG_LED_ON : XPOWERS_CHG_LED_OFF); | ||
} | ||
} | ||
} ledPmuHwPin; | ||
|
||
// In some cases we need to drive a PMU LED and a normal LED | ||
static GpioSplitter ledFinalPin(&ledHwPin, &ledPmuHwPin); | ||
#else | ||
static GpioPin &ledFinalPin = ledHwPin; | ||
#endif | ||
|
||
#ifdef USE_POWERMON | ||
/** | ||
* We monitor changes to the LED drive output because we use that as a sanity test in our power monitor stuff. | ||
*/ | ||
class MonitoredLedPin : public GpioPin | ||
{ | ||
public: | ||
void set(bool value) | ||
{ | ||
if (powerMon) { | ||
if (value) | ||
powerMon->setState(meshtastic_PowerMon_State_LED_On); | ||
else | ||
powerMon->clearState(meshtastic_PowerMon_State_LED_On); | ||
} | ||
ledFinalPin.set(value); | ||
} | ||
} monitoredLedPin; | ||
#else | ||
static GpioPin &monitoredLedPin = ledFinalPin; | ||
#endif | ||
|
||
static GpioBinaryTransformer ledForcer(&ledForceOn, &ledBlink, &monitoredLedPin, GpioBinaryTransformer::Or); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#include "GpioLogic.h" | ||
#include "configuration.h" | ||
|
||
/** | ||
* ledForceOn and ledForceOff both override the normal ledBlinker behavior (which is controlled by main) | ||
*/ | ||
extern GpioVirtPin ledForceOn, ledBlink; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.