Skip to content

Commit

Permalink
Merge pull request #4527 from geeksville/pr-fix4154
Browse files Browse the repository at this point in the history
for #4154 Only enable Vext regulator when needed for either Screen or GPS
  • Loading branch information
caveman99 authored Sep 2, 2024
2 parents c8bf43d + 367d787 commit 0588d69
Show file tree
Hide file tree
Showing 30 changed files with 255 additions and 172 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build_native.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
build-native:
runs-on: ubuntu-latest
steps:
- name: Install libbluetooth
- name: Install libs needed for native build
shell: bash
run: |
sudo apt-get update --fix-missing
Expand Down
22 changes: 21 additions & 1 deletion src/GpioLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,21 @@ void GpioVirtPin::set(bool value)
}
}

void GpioHwPin::set(bool value)
{
// if (num == 3) LOG_DEBUG("Setting pin %d to %d\n", num, value);
pinMode(num, OUTPUT);
digitalWrite(num, value);
}

GpioTransformer::GpioTransformer(GpioPin *outPin) : outPin(outPin) {}

void GpioTransformer::set(bool value)
{
outPin->set(value);
}

GpioNotTransformer::GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin) : GpioTransformer(outPin), inPin(inPin)
GpioUnaryTransformer::GpioUnaryTransformer(GpioVirtPin *inPin, GpioPin *outPin) : GpioTransformer(outPin), inPin(inPin)
{
assert(!inPin->dependentPin); // We only allow one dependent pin
inPin->dependentPin = this;
Expand All @@ -27,6 +34,18 @@ GpioNotTransformer::GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin) : Gp
// update();
}

/**
* Update the output pin based on the current state of the input pin.
*/
void GpioUnaryTransformer::update()
{
auto p = inPin->get();
if (p == GpioVirtPin::PinState::Unset)
return; // Not yet fully initialized

set(p);
}

/**
* Update the output pin based on the current state of the input pin.
*/
Expand Down Expand Up @@ -69,6 +88,7 @@ void GpioBinaryTransformer::update()
newValue = (GpioVirtPin::PinState)(p1 && p2);
break;
case Or:
// LOG_DEBUG("Doing GPIO OR\n");
newValue = (GpioVirtPin::PinState)(p1 || p2);
break;
case Xor:
Expand Down
30 changes: 23 additions & 7 deletions src/GpioLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class GpioHwPin : public GpioPin
public:
explicit GpioHwPin(uint32_t num) : num(num) {}

void set(bool value) { digitalWrite(num, value); }
void set(bool value);
};

class GpioTransformer;
Expand All @@ -42,7 +42,7 @@ class GpioBinaryTransformer;
class GpioVirtPin : public GpioPin
{
friend class GpioBinaryTransformer;
friend class GpioNotTransformer;
friend class GpioUnaryTransformer;

public:
enum PinState { On = true, Off = false, Unset = 2 };
Expand Down Expand Up @@ -79,25 +79,41 @@ class GpioTransformer
};

/**
* A transformer that performs a unary NOT operation from an input.
* A transformer that just drives a hw pin based on a virtual pin.
*/
class GpioNotTransformer : public GpioTransformer
class GpioUnaryTransformer : public GpioTransformer
{
public:
GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin);
GpioUnaryTransformer(GpioVirtPin *inPin, GpioPin *outPin);

protected:
friend class GpioVirtPin;

/**
* Update the output pin based on the current state of the input pin.
*/
void update();
virtual void update();

private:
GpioVirtPin *inPin;
};

/**
* A transformer that performs a unary NOT operation from an input.
*/
class GpioNotTransformer : public GpioUnaryTransformer
{
public:
GpioNotTransformer(GpioVirtPin *inPin, GpioPin *outPin) : GpioUnaryTransformer(inPin, outPin) {}

protected:
friend class GpioVirtPin;

/**
* Update the output pin based on the current state of the input pin.
*/
void update();
};

/**
* A transformer that combines multiple virtual pins to drive an output pin
*/
Expand Down
60 changes: 28 additions & 32 deletions src/Power.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,30 @@ using namespace meshtastic;
*/
static HasBatteryLevel *batteryLevel; // Default to NULL for no battery level sensor

static void adcEnable()
{
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
#ifdef ADC_USE_PULLUP
pinMode(ADC_CTRL, INPUT_PULLUP);
#else
pinMode(ADC_CTRL, OUTPUT);
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
#endif
delay(10);
#endif
}

static void adcDisable()
{
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
#ifdef ADC_USE_PULLUP
pinMode(ADC_CTRL, INPUT_PULLDOWN);
#else
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
#endif
#endif
}

/**
* A simple battery level sensor that assumes the battery voltage is attached via a voltage-divider to an analog input
*/
Expand Down Expand Up @@ -226,25 +250,19 @@ class AnalogBatteryLevel : public HasBatteryLevel
uint32_t raw = 0;
float scaled = 0;

adcEnable();
#ifdef ARCH_ESP32 // ADC block for espressif platforms
raw = espAdcRead();
scaled = esp_adc_cal_raw_to_voltage(raw, adc_characs);
scaled *= operativeAdcMultiplier;
#else // block for all other platforms
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
pinMode(ADC_CTRL, OUTPUT);
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
delay(10);
#endif
#else // block for all other platforms
for (uint32_t i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
raw += analogRead(BATTERY_PIN);
}
raw = raw / BATTERY_SENSE_SAMPLES;
scaled = operativeAdcMultiplier * ((1000 * AREF_VOLTAGE) / pow(2, BATTERY_SENSE_RESOLUTION_BITS)) * raw;
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
#endif
#endif
adcDisable();

if (!initial_read_done) {
// Flush the smoothing filter with an ADC reading, if the reading is plausibly correct
Expand Down Expand Up @@ -275,11 +293,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
uint8_t raw_c = 0; // raw reading counter

#ifndef BAT_MEASURE_ADC_UNIT // ADC1
#ifdef ADC_CTRL // enable adc voltage divider when we need to read
pinMode(ADC_CTRL, OUTPUT);
digitalWrite(ADC_CTRL, ADC_CTRL_ENABLED);
delay(10);
#endif
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
int val_ = adc1_get_raw(adc_channel);
if (val_ >= 0) { // save only valid readings
Expand All @@ -288,18 +301,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
}
// delayMicroseconds(100);
}
#ifdef ADC_CTRL // disable adc voltage divider when we need to read
digitalWrite(ADC_CTRL, !ADC_CTRL_ENABLED);
#endif
#else // ADC2
#ifdef ADC_CTRL
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0)
pinMode(ADC_CTRL, OUTPUT);
digitalWrite(ADC_CTRL, LOW); // ACTIVE LOW
delay(10);
#endif
#endif // End ADC_CTRL

#else // ADC2
#ifdef CONFIG_IDF_TARGET_ESP32S3 // ESP32S3
// ADC2 wifi bug workaround not required, breaks compile
// On ESP32S3, ADC2 can take turns with Wifi (?)
Expand Down Expand Up @@ -334,12 +336,6 @@ class AnalogBatteryLevel : public HasBatteryLevel
}
#endif // BAT_MEASURE_ADC_UNIT

#ifdef ADC_CTRL
#if defined(HELTEC_WIRELESS_PAPER) || defined(HELTEC_WIRELESS_PAPER_V1_0)
digitalWrite(ADC_CTRL, HIGH);
#endif
#endif // End ADC_CTRL

#endif // End BAT_MEASURE_ADC_UNIT
return (raw / (raw_c < 1 ? 1 : raw_c));
}
Expand Down
5 changes: 5 additions & 0 deletions src/configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
/* Step #1: offer chance for variant-specific defines */
#include "variant.h"

#if defined(VEXT_ENABLE) && !defined(VEXT_ON_VALUE)
// Older variant.h files might not be defining this value, so stay with the old default
#define VEXT_ON_VALUE LOW
#endif

#ifndef GPS_BAUDRATE
#define GPS_BAUDRATE 9600
#endif
Expand Down
26 changes: 16 additions & 10 deletions src/gps/GPS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#if !MESHTASTIC_EXCLUDE_GPS
#include "Default.h"
#include "GPS.h"
#include "GpioLogic.h"
#include "NodeDB.h"
#include "PowerMon.h"
#include "RTC.h"
Expand Down Expand Up @@ -875,16 +876,8 @@ void GPS::writePinEN(bool on)
if (HW_VENDOR == meshtastic_HardwareModel_RAK4631 && (rotaryEncoderInterruptImpl1 || upDownInterruptImpl1))
return;

// Abort: if pin unset
if (!en_gpio)
return;

// Determine new value for the pin
bool val = GPS_EN_ACTIVE ? on : !on;

// Write and log
pinMode(en_gpio, OUTPUT);
digitalWrite(en_gpio, val);
enablePin->set(on);
#ifdef GPS_EXTRAVERBOSE
LOG_DEBUG("Pin EN %s\n", val == HIGH ? "HIGH" : "LOW");
#endif
Expand Down Expand Up @@ -1421,7 +1414,20 @@ GPS *GPS::createGps()
GPS *new_gps = new GPS;
new_gps->rx_gpio = _rx_gpio;
new_gps->tx_gpio = _tx_gpio;
new_gps->en_gpio = _en_gpio;

GpioVirtPin *virtPin = new GpioVirtPin();
new_gps->enablePin = virtPin; // Always at least populate a virtual pin
if (_en_gpio) {
GpioPin *p = new GpioHwPin(_en_gpio);

if (!GPS_EN_ACTIVE) { // Need to invert the pin before hardware
new GpioNotTransformer(
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
} else {
new GpioUnaryTransformer(
virtPin, p); // We just leave this created object on the heap so it can stay watching virtPin and driving en_gpio
}
}

#ifdef PIN_GPS_PPS
// pulse per second
Expand Down
11 changes: 9 additions & 2 deletions src/gps/GPS.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#if !MESHTASTIC_EXCLUDE_GPS

#include "GPSStatus.h"
#include "GpioLogic.h"
#include "Observer.h"
#include "TinyGPS++.h"
#include "concurrency/OSThread.h"
Expand Down Expand Up @@ -73,7 +74,6 @@ class GPS : private concurrency::OSThread
uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0;
uint32_t rx_gpio = 0;
uint32_t tx_gpio = 0;
uint32_t en_gpio = 0;

int speedSelect = 0;
int probeTries = 2;
Expand Down Expand Up @@ -152,6 +152,13 @@ class GPS : private concurrency::OSThread

meshtastic_Position p = meshtastic_Position_init_default;

/** This is normally bound to config.position.gps_en_gpio but some rare boards (like heltec tracker) need more advanced
* implementations. Those boards will set this public variable to a custom implementation.
*
* Normally set by GPS::createGPS()
*/
GpioVirtPin *enablePin = NULL;

GPS() : concurrency::OSThread("GPS") {}

virtual ~GPS();
Expand Down Expand Up @@ -303,4 +310,4 @@ class GPS : private concurrency::OSThread
};

extern GPS *gps;
#endif // Exclude GPS
#endif // Exclude GPS
Loading

0 comments on commit 0588d69

Please sign in to comment.