103 lines
5.5 KiB
C++
103 lines
5.5 KiB
C++
#ifndef WLED_PIN_MANAGER_H
|
|
#define WLED_PIN_MANAGER_H
|
|
/*
|
|
* Registers pins so there is no attempt for two interfaces to use the same pin
|
|
*/
|
|
#include <Arduino.h>
|
|
#include "const.h" // for USERMOD_* values
|
|
|
|
typedef struct PinManagerPinType {
|
|
int8_t pin;
|
|
bool isOutput;
|
|
} managed_pin_type;
|
|
|
|
/*
|
|
* Allows PinManager to "lock" an allocation to a specific
|
|
* owner, so someone else doesn't accidentally de-allocate
|
|
* a pin it hasn't allocated. Also enhances debugging.
|
|
*
|
|
* RAM Cost:
|
|
* 17 bytes on ESP8266
|
|
* 40 bytes on ESP32
|
|
*/
|
|
enum struct PinOwner : uint8_t {
|
|
None = 0, // default == legacy == unspecified owner
|
|
// High bit is set for all built-in pin owners
|
|
Ethernet = 0x81,
|
|
BusDigital = 0x82,
|
|
BusDigital2 = 0x83,
|
|
BusPwm = 0x84, // 'BusP' == PWM output using BusPwm
|
|
Button = 0x85, // 'Butn' == button from configuration
|
|
IR = 0x86, // 'IR' == IR receiver pin from configuration
|
|
Relay = 0x87, // 'Rly' == Relay pin from configuration
|
|
SPI_RAM = 0x88, // 'SpiR' == SPI RAM
|
|
DebugOut = 0x89, // 'Dbg' == debug output always IO1
|
|
DMX = 0x8A, // 'DMX' == hard-coded to IO2
|
|
// Use UserMod IDs from const.h here
|
|
UM_Unspecified = USERMOD_ID_UNSPECIFIED, // 0x01
|
|
UM_RGBRotaryEncoder = USERMOD_ID_UNSPECIFIED, // 0x01 // No define in const.h for this user module -- consider adding?
|
|
UM_Example = USERMOD_ID_EXAMPLE, // 0x02 // Usermod "usermod_v2_example.h"
|
|
UM_Temperature = USERMOD_ID_TEMPERATURE, // 0x03 // Usermod "usermod_temperature.h"
|
|
// #define USERMOD_ID_FIXNETSERVICES // 0x04 // Usermod "usermod_Fix_unreachable_netservices.h" -- Does not allocate pins
|
|
UM_PIR = USERMOD_ID_PIRSWITCH, // 0x05 // Usermod "usermod_PIR_sensor_switch.h"
|
|
// #define USERMOD_ID_IMU // 0x06 // Usermod "usermod_mpu6050_imu.h" -- Uses "standard" I2C pins ... TODO -- enable shared I2C bus use
|
|
UM_FourLineDisplay = USERMOD_ID_FOUR_LINE_DISP, // 0x07 // Usermod "usermod_v2_four_line_display.h
|
|
UM_RotaryEncoderUI = USERMOD_ID_ROTARY_ENC_UI, // 0x08 // Usermod "usermod_v2_rotary_encoder_ui.h"
|
|
// #define USERMOD_ID_AUTO_SAVE // 0x09 // Usermod "usermod_v2_auto_save.h" -- Does not allocate pins
|
|
// #define USERMOD_ID_DHT // 0x0A // Usermod "usermod_dht.h" -- Statically allocates pins, not compatible with pinManager?
|
|
// #define USERMOD_ID_MODE_SORT // 0x0B // Usermod "usermod_v2_mode_sort.h" -- Does not allocate pins
|
|
// #define USERMOD_ID_VL53L0X // 0x0C // Usermod "usermod_vl53l0x_gestures.h" -- Uses "standard" I2C pins ... TODO -- enable shared I2C bus use
|
|
UM_MultiRelay = USERMOD_ID_MULTI_RELAY, // 0x0D // Usermod "usermod_multi_relay.h"
|
|
UM_AnimatedStaircase = USERMOD_ID_ANIMATED_STAIRCASE, // 0x0E // Usermod "Animated_Staircase.h"
|
|
// #define USERMOD_ID_RTC // 0x0F // Usermod "usermod_rtc.h" -- Uses "standard" I2C pins ... TODO -- enable shared I2C bus use
|
|
// #define USERMOD_ID_ELEKSTUBE_IPS // 0x10 // Usermod "usermod_elekstube_ips.h" -- Uses quite a few pins ... see Hardware.h and User_Setup.h
|
|
// #define USERMOD_ID_SN_PHOTORESISTOR // 0x11 // Usermod "usermod_sn_photoresistor.h" -- Uses hard-coded pin (PHOTORESISTOR_PIN == A0), but could be easily updated to use pinManager
|
|
};
|
|
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");
|
|
|
|
class PinManagerClass {
|
|
private:
|
|
#ifdef ESP8266
|
|
uint8_t pinAlloc[3] = {0x00, 0x00, 0x00}; //24bit, 1 bit per pin, we use first 17bits
|
|
PinOwner ownerTag[17] = { PinOwner::None };
|
|
#else
|
|
uint8_t pinAlloc[5] = {0x00, 0x00, 0x00, 0x00, 0x00}; //40bit, 1 bit per pin, we use all bits
|
|
uint8_t ledcAlloc[2] = {0x00, 0x00}; //16 LEDC channels
|
|
PinOwner ownerTag[40] = { PinOwner::None };
|
|
#endif
|
|
|
|
public:
|
|
// De-allocates a single pin
|
|
bool deallocatePin(byte gpio, PinOwner tag);
|
|
// Allocates a single pin, with an owner tag.
|
|
// De-allocation requires the same owner tag (or override)
|
|
bool allocatePin(byte gpio, bool output, PinOwner tag);
|
|
// Allocates all the pins, or allocates none of the pins, with owner tag.
|
|
// Provided to simplify error condition handling in clients
|
|
// using more than one pin, such as I2C, SPI, rotary encoders,
|
|
// ethernet, etc..
|
|
bool allocateMultiplePins(const managed_pin_type * mptArray, byte arrayElementCount, PinOwner tag );
|
|
|
|
#if !defined(ESP8266) // ESP8266 compiler doesn't understand deprecated attribute
|
|
[[deprecated("Replaced by three-parameter allocatePin(gpio, output, ownerTag), for improved debugging")]]
|
|
#endif
|
|
inline bool allocatePin(byte gpio, bool output = true) { return allocatePin(gpio, output, PinOwner::None); }
|
|
#if !defined(ESP8266) // ESP8266 compiler doesn't understand deprecated attribute
|
|
[[deprecated("Replaced by three-parameter deallocatePin(gpio, output, ownerTag), for improved debugging")]]
|
|
#endif
|
|
inline void deallocatePin(byte gpio) { deallocatePin(gpio, PinOwner::None); }
|
|
|
|
// will return true for reserved pins
|
|
bool isPinAllocated(byte gpio, PinOwner tag = PinOwner::None);
|
|
// will return false for reserved pins
|
|
bool isPinOk(byte gpio, bool output = true);
|
|
|
|
#ifdef ARDUINO_ARCH_ESP32
|
|
byte allocateLedc(byte channels);
|
|
void deallocateLedc(byte pos, byte channels);
|
|
#endif
|
|
};
|
|
|
|
extern PinManagerClass pinManager;
|
|
#endif
|