2021-01-15 23:50:43 +00:00
# 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>
2024-08-26 22:21:24 +00:00
# ifdef ARDUINO_ARCH_ESP32
# include "driver/ledc.h" // needed for analog/LEDC channel counts
# endif
2021-08-23 12:14:48 +00:00
# include "const.h" // for USERMOD_* values
typedef struct PinManagerPinType {
2021-09-04 14:45:08 +00:00
int8_t pin ;
bool isOutput ;
2021-08-23 12:14:48 +00:00
} 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 .
2023-01-06 08:24:29 +00:00
*
2021-08-23 12:14:48 +00:00
* RAM Cost :
* 17 bytes on ESP8266
* 40 bytes on ESP32
*/
enum struct PinOwner : uint8_t {
2021-11-19 20:49:23 +00:00
None = 0 , // default == legacy == unspecified owner
2021-08-23 12:14:48 +00:00
// High bit is set for all built-in pin owners
Ethernet = 0x81 ,
BusDigital = 0x82 ,
2022-06-20 20:17:01 +00:00
BusOnOff = 0x83 ,
2021-08-23 12:14:48 +00:00
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
2021-11-19 20:49:23 +00:00
HW_I2C = 0x8B , // 'I2C' == hardware I2C pins (4&5 on ESP8266, 21&22 on ESP32)
2022-08-14 11:05:59 +00:00
HW_SPI = 0x8C , // 'SPI' == hardware (V)SPI pins (13,14&15 on ESP8266, 5,18&23 on ESP32)
2021-08-23 12:14:48 +00:00
// Use UserMod IDs from const.h here
UM_Unspecified = USERMOD_ID_UNSPECIFIED , // 0x01
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"
2024-01-07 19:32:22 +00:00
UM_IMU = USERMOD_ID_IMU , // 0x06 // Usermod "usermod_mpu6050_imu.h" -- Interrupt pin
2021-11-19 20:49:23 +00:00
UM_FourLineDisplay = USERMOD_ID_FOUR_LINE_DISP , // 0x07 // Usermod "usermod_v2_four_line_display.h -- May use "standard" HW_I2C pins
2021-08-23 12:14:48 +00:00
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?
2021-11-19 20:49:23 +00:00
// #define USERMOD_ID_VL53L0X // 0x0C // Usermod "usermod_vl53l0x_gestures.h" -- Uses "standard" HW_I2C pins
2021-08-23 12:14:48 +00:00
UM_MultiRelay = USERMOD_ID_MULTI_RELAY , // 0x0D // Usermod "usermod_multi_relay.h"
UM_AnimatedStaircase = USERMOD_ID_ANIMATED_STAIRCASE , // 0x0E // Usermod "Animated_Staircase.h"
2022-12-28 21:40:13 +00:00
UM_Battery = USERMOD_ID_BATTERY , //
2023-01-06 08:24:29 +00:00
// #define USERMOD_ID_RTC // 0x0F // Usermod "usermod_rtc.h" -- Uses "standard" HW_I2C pins
2021-08-23 12:14:48 +00:00
// #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
2024-05-20 12:45:01 +00:00
UM_BH1750 = USERMOD_ID_BH1750 , // 0x14 // Usermod "bh1750.h -- Uses "standard" HW_I2C pins
2021-11-19 20:49:23 +00:00
UM_RGBRotaryEncoder = USERMOD_RGB_ROTARY_ENCODER , // 0x16 // Usermod "rgb-rotary-encoder.h"
2022-06-10 22:50:29 +00:00
UM_QuinLEDAnPenta = USERMOD_ID_QUINLED_AN_PENTA , // 0x17 // Usermod "quinled-an-penta.h"
2022-12-28 00:50:04 +00:00
UM_BME280 = USERMOD_ID_BME280 , // 0x1E // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
UM_Audioreactive = USERMOD_ID_AUDIOREACTIVE , // 0x20 // Usermod "audio_reactive.h"
UM_SdCard = USERMOD_ID_SD_CARD , // 0x25 // Usermod "usermod_sd_card.h"
2024-02-06 13:47:20 +00:00
UM_PWM_OUTPUTS = USERMOD_ID_PWM_OUTPUTS , // 0x26 // Usermod "usermod_pwm_outputs.h"
2024-03-09 18:06:30 +00:00
UM_LDR_DUSK_DAWN = USERMOD_ID_LDR_DUSK_DAWN , // 0x2B // Usermod "usermod_LDR_Dusk_Dawn_v2.h"
2024-05-20 12:45:01 +00:00
UM_MAX17048 = USERMOD_ID_MAX17048 , // 0x2F // Usermod "usermod_max17048.h"
2024-08-08 03:13:33 +00:00
UM_BME68X = USERMOD_ID_BME68X , // 0x31 // Usermod "usermod_bme68x.h -- Uses "standard" HW_I2C pins
2024-08-26 22:21:24 +00:00
UM_PIXELS_DICE_TRAY = USERMOD_ID_PIXELS_DICE_TRAY // 0x35 // Usermod "pixels_dice_tray.h" -- Needs compile time specified 6 pins for display including SPI.
2021-08-23 12:14:48 +00:00
} ;
static_assert ( 0u = = static_cast < uint8_t > ( PinOwner : : None ) , " PinOwner::None must be zero, so default array initialization works as expected " ) ;
2021-01-15 23:50:43 +00:00
2024-09-19 19:44:11 +00:00
class PinManager {
2021-01-15 23:50:43 +00:00
private :
2024-08-26 22:21:24 +00:00
# ifdef ESP8266
2024-09-19 19:44:11 +00:00
# define WLED_NUM_PINS (GPIO_PIN_COUNT+1) // somehow they forgot GPIO 16 (0-16==17)
static uint32_t pinAlloc ; // 1 bit per pin, we use first 17bits
2024-08-26 22:21:24 +00:00
# else
2024-09-19 19:44:11 +00:00
# define WLED_NUM_PINS (GPIO_PIN_COUNT)
static uint64_t pinAlloc ; // 1 bit per pin, we use 50 bits on ESP32-S3
static uint16_t ledcAlloc ; // up to 16 LEDC channels (WLED_MAX_ANALOG_CHANNELS)
2024-08-26 22:21:24 +00:00
# endif
2024-09-19 19:44:11 +00:00
static uint8_t i2cAllocCount ; // allow multiple allocation of I2C bus pins but keep track of allocations
static uint8_t spiAllocCount ; // allow multiple allocation of SPI bus pins but keep track of allocations
static PinOwner ownerTag [ WLED_NUM_PINS ] ;
2021-01-15 23:50:43 +00:00
public :
2024-09-19 19:44:11 +00:00
// De-allocates a single pin
static bool deallocatePin ( byte gpio , PinOwner tag ) ;
// De-allocates multiple pins but only if all can be deallocated (PinOwner has to be specified)
static bool deallocateMultiplePins ( const uint8_t * pinArray , byte arrayElementCount , PinOwner tag ) ;
static bool deallocateMultiplePins ( const managed_pin_type * pinArray , byte arrayElementCount , PinOwner tag ) ;
// Allocates a single pin, with an owner tag.
// De-allocation requires the same owner tag (or override)
static 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..
static bool allocateMultiplePins ( const managed_pin_type * mptArray , byte arrayElementCount , PinOwner tag ) ;
2021-08-23 12:14:48 +00:00
2024-09-19 19:44:11 +00:00
[ [ deprecated ( " Replaced by three-parameter allocatePin(gpio, output, ownerTag), for improved debugging " ) ] ]
static inline bool allocatePin ( byte gpio , bool output = true ) { return allocatePin ( gpio , output , PinOwner : : None ) ; }
[ [ deprecated ( " Replaced by two-parameter deallocatePin(gpio, ownerTag), for improved debugging " ) ] ]
static inline void deallocatePin ( byte gpio ) { deallocatePin ( gpio , PinOwner : : None ) ; }
2021-08-23 12:14:48 +00:00
2024-09-19 19:44:11 +00:00
// will return true for reserved pins
static bool isPinAllocated ( byte gpio , PinOwner tag = PinOwner : : None ) ;
// will return false for reserved pins
static bool isPinOk ( byte gpio , bool output = true ) ;
static bool isReadOnlyPin ( byte gpio ) ;
2024-09-01 19:31:19 +00:00
2024-09-19 19:44:11 +00:00
static PinOwner getPinOwner ( byte gpio ) ;
2021-11-17 10:13:07 +00:00
2024-09-19 19:44:11 +00:00
# ifdef ARDUINO_ARCH_ESP32
static byte allocateLedc ( byte channels ) ;
static void deallocateLedc ( byte pos , byte channels ) ;
# endif
2021-01-15 23:50:43 +00:00
} ;
2024-09-19 19:44:11 +00:00
//extern PinManager pinManager;
2021-08-23 12:14:48 +00:00
# endif