Change GPIO input to polling (#484)
* add code to attach timer isr * call timer ISR every 100 ms * implement gpio input logic * do not attach ISR for general input PINs * add debounce code * execute lock actions on GPIO input * only register timer ISR if input PINs are configured * remove gpio2go lib
This commit is contained in:
@@ -47,9 +47,6 @@ set(SRCFILES
|
||||
../lib/nuki_ble/src/NukiUtils.cpp
|
||||
../lib/nuki_ble/src/NukiLockUtils.cpp
|
||||
../lib/nuki_ble/src/NukiOpenerUtils.cpp
|
||||
../lib/gpio2go/src/Gpio2Go.cpp
|
||||
../lib/gpio2go/src/InterruptMode.h
|
||||
../lib/gpio2go/src/PinMode.h
|
||||
../lib/BleScanner/src/BleInterfaces.h
|
||||
../lib/BleScanner/src/BleScanner.cpp
|
||||
../lib/MqttLogger/src/MqttLogger.cpp
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.0.0)
|
||||
|
||||
if(NOT ARDUINO_BOARD)
|
||||
set(ARDUINO_BOARD "ESP32 Dev Module [esp32.esp32]")
|
||||
endif()
|
||||
|
||||
project(gpio2go CXX)
|
||||
|
||||
# ARDUHAL_LOG_LEVEL_NONE, define ARDUHAL_LOG_LEVEL_ERROR, define ARDUHAL_LOG_LEVEL_WARN, define ARDUHAL_LOG_LEVEL_INFO,
|
||||
# define ARDUHAL_LOG_LEVEL_DEBUG, define ARDUHAL_LOG_LEVEL_VERBOSE
|
||||
|
||||
set(LOG_LEVEL ARDUHAL_LOG_LEVEL_NONE)
|
||||
|
||||
#add_compile_definitions(DEBUG_SENSE_NUKI)
|
||||
#add_compile_definitions(DEBUG_NUKI_COMMAND)
|
||||
#add_compile_definitions(DEBUG_NUKI_CONNECT)
|
||||
#add_compile_definitions(DEBUG_NUKI_COMMUNICATION)
|
||||
#add_compile_definitions(DEBUG_NUKI_HEX_DATA)
|
||||
#add_compile_definitions(DEBUG_NUKI_READABLE_DATA)
|
||||
|
||||
add_compile_definitions(ESP_PLATFORM)
|
||||
add_compile_definitions(ESP32)
|
||||
add_compile_definitions(ARDUINO_ARCH_ESP32)
|
||||
|
||||
include_directories(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
src
|
||||
)
|
||||
|
||||
set(SRCFILES
|
||||
src/PinMode.h
|
||||
src/Gpio2Go.cpp
|
||||
src/InterruptMode.h
|
||||
)
|
||||
|
||||
file(GLOB_RECURSE SRCFILESREC
|
||||
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
main.cpp
|
||||
${SRCFILES}
|
||||
${SRCFILESREC}
|
||||
)
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
ARDUHAL_LOG_LEVEL=${LOG_LEVEL}
|
||||
CORE_DEBUG_LEVEL=${LOG_LEVEL}
|
||||
)
|
||||
|
||||
target_link_arduino_libraries(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
core
|
||||
)
|
||||
|
||||
target_enable_arduino_upload(${PROJECT_NAME})
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Jan-Ole Schümann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1 +0,0 @@
|
||||
# gpio2go
|
||||
@@ -1,38 +0,0 @@
|
||||
#include "Arduino.h"
|
||||
#include "Gpio2Go.h"
|
||||
|
||||
#define INPUT_PIN 21
|
||||
|
||||
bool hasMessage = false;
|
||||
String message;
|
||||
|
||||
void inputCb(const int & pin)
|
||||
{
|
||||
message = "";
|
||||
message.concat("Input, Pin ");
|
||||
message.concat(pin);
|
||||
message.concat(" ");
|
||||
message.concat(", state ");
|
||||
message.concat(digitalRead(INPUT_PIN) ? "High" : "Low");
|
||||
hasMessage = true;
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
delay(1100);
|
||||
Serial.println(F("Started"));
|
||||
Gpio2Go::configurePin(INPUT_PIN, PinMode::InputPullup, InterruptMode::Change, 200);
|
||||
Gpio2Go::subscribe(inputCb);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
delay(100);
|
||||
if(hasMessage)
|
||||
{
|
||||
hasMessage = false;
|
||||
Serial.println(message);
|
||||
}
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
#include "Gpio2Go.h"
|
||||
#include <stdexcept>
|
||||
|
||||
void Gpio2Go::configurePin(int pin, PinMode pin_Mode, InterruptMode interrupt_Mode, uint16_t timeoutAfterTriggerMS)
|
||||
{
|
||||
timeoutDurations[pin - GPIO2GO_NR_FIRST_PIN] = timeoutAfterTriggerMS;
|
||||
|
||||
switch(pin_Mode)
|
||||
{
|
||||
case PinMode::InputPullup:
|
||||
pinMode(pin, INPUT_PULLUP);
|
||||
attachIsr(pin, interrupt_Mode);
|
||||
break;
|
||||
case PinMode::InputPullDown:
|
||||
pinMode(pin, INPUT_PULLDOWN);
|
||||
attachIsr(pin, interrupt_Mode);
|
||||
break;
|
||||
case PinMode::Output:
|
||||
pinMode(pin, OUTPUT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio2Go::subscribe(std::function<void(const int &)> callback)
|
||||
{
|
||||
subscriptions.push_back(callback);
|
||||
}
|
||||
|
||||
unsigned long Gpio2Go::getLastTriggeredMillis(const int &pin)
|
||||
{
|
||||
if(pin >= GPIO2GO_NR_FIRST_PIN && pin <= (GPIO2GO_NR_OF_PINS + GPIO2GO_NR_FIRST_PIN))
|
||||
{
|
||||
return lastTriggeredTimestamps[pin - GPIO2GO_NR_FIRST_PIN];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Gpio2Go::attachIsr(int pin, InterruptMode interruptMode)
|
||||
{
|
||||
switch(pin)
|
||||
{
|
||||
case 2:
|
||||
attachInterrupt(2, isrGpio2, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 4:
|
||||
attachInterrupt(4, isrGpio4, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 5:
|
||||
attachInterrupt(5, isrGpio5, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 13:
|
||||
attachInterrupt(13, isrGpio13, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 14:
|
||||
attachInterrupt(14, isrGpio14, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 15:
|
||||
attachInterrupt(15, isrGpio15, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 16:
|
||||
attachInterrupt(16, isrGpio16, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 17:
|
||||
attachInterrupt(17, isrGpio17, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 18:
|
||||
attachInterrupt(18, isrGpio18, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 19:
|
||||
attachInterrupt(19, isrGpio19, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 20:
|
||||
attachInterrupt(20, isrGpio20, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 21:
|
||||
attachInterrupt(21, isrGpio21, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 22:
|
||||
attachInterrupt(22, isrGpio22, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 23:
|
||||
attachInterrupt(23, isrGpio23, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 24:
|
||||
attachInterrupt(24, isrGpio24, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 25:
|
||||
attachInterrupt(25, isrGpio25, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 26:
|
||||
attachInterrupt(26, isrGpio26, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 27:
|
||||
attachInterrupt(27, isrGpio27, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 32:
|
||||
attachInterrupt(32, isrGpio32, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
case 33:
|
||||
attachInterrupt(33, isrGpio33, resolveInterruptMode(interruptMode));
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Gpio2Go: Unsupported pin.");
|
||||
}
|
||||
}
|
||||
|
||||
int Gpio2Go::resolveInterruptMode(InterruptMode interruptMode)
|
||||
{
|
||||
switch(interruptMode)
|
||||
{
|
||||
case InterruptMode::Rising:
|
||||
return RISING;
|
||||
case InterruptMode::Falling:
|
||||
return FALLING;
|
||||
case InterruptMode::Change:
|
||||
return CHANGE;
|
||||
case InterruptMode::OnLow:
|
||||
return ONLOW;
|
||||
case InterruptMode::OnHigh:
|
||||
return ONHIGH;
|
||||
default:
|
||||
throw std::runtime_error("Gpio2Go: Unsupported interrupt mode.");
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio2Go::isrHandler(int pin)
|
||||
{
|
||||
unsigned long timeout = lastTriggeredTimestamps[pin - GPIO2GO_NR_FIRST_PIN];
|
||||
if(timeoutDurations[pin - GPIO2GO_NR_FIRST_PIN] != 0 && (millis() - timeout) < timeoutDurations[pin - GPIO2GO_NR_FIRST_PIN]) return;
|
||||
lastTriggeredTimestamps[pin - GPIO2GO_NR_FIRST_PIN] = millis();
|
||||
|
||||
bool state = digitalRead(pin) == HIGH;
|
||||
|
||||
for(const auto& callback : subscriptions)
|
||||
{
|
||||
callback(pin);
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio2()
|
||||
{
|
||||
isrHandler(2);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio4()
|
||||
{
|
||||
isrHandler(4);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio5()
|
||||
{
|
||||
isrHandler(5);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio13()
|
||||
{
|
||||
isrHandler(13);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio14()
|
||||
{
|
||||
isrHandler(14);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio15()
|
||||
{
|
||||
isrHandler(15);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio16()
|
||||
{
|
||||
isrHandler(16);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio17()
|
||||
{
|
||||
isrHandler(17);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio18()
|
||||
{
|
||||
isrHandler(18);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio19()
|
||||
{
|
||||
isrHandler(19);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio20()
|
||||
{
|
||||
isrHandler(20);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio21()
|
||||
{
|
||||
isrHandler(21);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio22()
|
||||
{
|
||||
isrHandler(22);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio23()
|
||||
{
|
||||
isrHandler(23);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio24()
|
||||
{
|
||||
isrHandler(24);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio25()
|
||||
{
|
||||
isrHandler(25);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio26()
|
||||
{
|
||||
isrHandler(26);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio27()
|
||||
{
|
||||
isrHandler(27);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio32()
|
||||
{
|
||||
isrHandler(32);
|
||||
}
|
||||
|
||||
void Gpio2Go::isrGpio33()
|
||||
{
|
||||
isrHandler(33);
|
||||
}
|
||||
|
||||
unsigned long Gpio2Go::lastTriggeredTimestamps[] = {0};
|
||||
uint16_t Gpio2Go::timeoutDurations[] = {0};
|
||||
std::vector<std::function<void(const int&)>> Gpio2Go::subscriptions;
|
||||
@@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <vector>
|
||||
#include "esp_attr.h"
|
||||
#include "PinMode.h"
|
||||
#include "InterruptMode.h"
|
||||
|
||||
#define GPIO2GO_NR_OF_PINS 31
|
||||
#define GPIO2GO_NR_FIRST_PIN 2
|
||||
|
||||
class Gpio2Go
|
||||
{
|
||||
public:
|
||||
static void configurePin(int pin, PinMode pin_Mode, InterruptMode interrupt_Mode, uint16_t timeoutAfterTriggerMS);
|
||||
static void subscribe(std::function<void(const int&)> callback);
|
||||
|
||||
unsigned long getLastTriggeredMillis(const int& pin);
|
||||
|
||||
private:
|
||||
static void attachIsr(int pin, InterruptMode interruptMode);
|
||||
static int resolveInterruptMode(InterruptMode interruptMode);
|
||||
|
||||
static void IRAM_ATTR isrHandler(int pin);
|
||||
static void IRAM_ATTR isrGpio2();
|
||||
static void IRAM_ATTR isrGpio4();
|
||||
static void IRAM_ATTR isrGpio5();
|
||||
static void IRAM_ATTR isrGpio13();
|
||||
static void IRAM_ATTR isrGpio14();
|
||||
static void IRAM_ATTR isrGpio15();
|
||||
static void IRAM_ATTR isrGpio16();
|
||||
static void IRAM_ATTR isrGpio17();
|
||||
static void IRAM_ATTR isrGpio18();
|
||||
static void IRAM_ATTR isrGpio19();
|
||||
static void IRAM_ATTR isrGpio20();
|
||||
static void IRAM_ATTR isrGpio21();
|
||||
static void IRAM_ATTR isrGpio22();
|
||||
static void IRAM_ATTR isrGpio23();
|
||||
static void IRAM_ATTR isrGpio24();
|
||||
static void IRAM_ATTR isrGpio25();
|
||||
static void IRAM_ATTR isrGpio26();
|
||||
static void IRAM_ATTR isrGpio27();
|
||||
static void IRAM_ATTR isrGpio32();
|
||||
static void IRAM_ATTR isrGpio33();
|
||||
|
||||
static unsigned long DRAM_ATTR lastTriggeredTimestamps[GPIO2GO_NR_OF_PINS];
|
||||
static uint16_t DRAM_ATTR timeoutDurations[GPIO2GO_NR_OF_PINS];
|
||||
static std::vector<std::function<void(const int&)>> DRAM_ATTR subscriptions;
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
enum class InterruptMode
|
||||
{
|
||||
Rising = 0x01,
|
||||
Falling = 0x02,
|
||||
Change = 0x03,
|
||||
OnLow = 0x04,
|
||||
OnHigh = 0x05
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
enum class PinMode
|
||||
{
|
||||
Output = 0x03,
|
||||
InputPullup = 0x05,
|
||||
InputPullDown = 0x09
|
||||
};
|
||||
|
||||
//#define INPUT 0x01
|
||||
//// Changed OUTPUT from 0x02 to behave the same as Arduino pinMode(pin,OUTPUT)
|
||||
//// where you can read the state of pin even when it is set as OUTPUT
|
||||
//#define OUTPUT 0x03
|
||||
//#define PULLUP 0x04
|
||||
//#define INPUT_PULLUP 0x05
|
||||
//#define PULLDOWN 0x08
|
||||
//#define INPUT_PULLDOWN 0x09
|
||||
//#define OPEN_DRAIN 0x10
|
||||
//#define OUTPUT_OPEN_DRAIN 0x12
|
||||
//#define ANALOG 0xC0
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#define NUKI_HUB_VERSION "9.01"
|
||||
#define NUKI_HUB_BUILD "unknownbuildnr"
|
||||
#define NUKI_HUB_DATE "2024-09-01"
|
||||
#define NUKI_HUB_DATE "2024-10-13"
|
||||
|
||||
#define GITHUB_LATEST_RELEASE_URL (char*)"https://github.com/technyon/nuki_hub/releases/latest"
|
||||
#define GITHUB_OTA_MANIFEST_URL (char*)"https://raw.githubusercontent.com/technyon/nuki_hub/binary/ota/manifest.json"
|
||||
|
||||
278
src/Gpio.cpp
278
src/Gpio.cpp
@@ -5,13 +5,11 @@
|
||||
#include "Logger.h"
|
||||
#include "PreferencesKeys.h"
|
||||
#include "RestartReason.h"
|
||||
#include "Gpio2Go.h"
|
||||
#include "networkDevices/LAN8720Definitions.h"
|
||||
#include "networkDevices/DM9051Definitions.h"
|
||||
#include "networkDevices/W5500Definitions.h"
|
||||
|
||||
Gpio* Gpio::_inst = nullptr;
|
||||
int64_t Gpio::_debounceTs = 0;
|
||||
const uint Gpio::_debounceTime = GPIO_DEBOUNCE_TIME;
|
||||
|
||||
Gpio::Gpio(Preferences* preferences)
|
||||
@@ -28,8 +26,101 @@ Gpio::Gpio(Preferences* preferences)
|
||||
_inst->init();
|
||||
}
|
||||
|
||||
|
||||
bool Gpio::isTriggered(const PinEntry& entry)
|
||||
{
|
||||
const int threshold = 3;
|
||||
|
||||
int state = digitalRead(entry.pin);
|
||||
|
||||
if(entry.role == PinRole::GeneralInputPullDown)
|
||||
{
|
||||
state = 1 - state;
|
||||
}
|
||||
|
||||
if(state == LOW)
|
||||
{
|
||||
if (_triggerCount[entry.pin] >= 0)
|
||||
{
|
||||
_triggerCount[entry.pin]++;
|
||||
}
|
||||
|
||||
if (_triggerCount[entry.pin] >= threshold)
|
||||
{
|
||||
_triggerCount[entry.pin] = -1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_triggerCount[entry.pin] < 0)
|
||||
{
|
||||
_triggerCount[entry.pin]--;
|
||||
|
||||
if(_triggerCount[entry.pin] <= -threshold)
|
||||
{
|
||||
_triggerCount[entry.pin] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Gpio::onTimer()
|
||||
{
|
||||
for(const auto& entry : _inst->_pinConfiguration)
|
||||
{
|
||||
switch(entry.role)
|
||||
{
|
||||
case PinRole::InputLock:
|
||||
case PinRole::InputUnlock:
|
||||
case PinRole::InputUnlatch:
|
||||
case PinRole::InputLockNgo:
|
||||
case PinRole::InputLockNgoUnlatch:
|
||||
case PinRole::InputElectricStrikeActuation:
|
||||
case PinRole::InputActivateRTO:
|
||||
case PinRole::InputActivateCM:
|
||||
case PinRole::InputDeactivateRtoCm:
|
||||
case PinRole::InputDeactivateRTO:
|
||||
case PinRole::InputDeactivateCM:
|
||||
case PinRole::GeneralInputPullDown:
|
||||
case PinRole::GeneralInputPullUp:
|
||||
if(isTriggered(entry))
|
||||
{
|
||||
_inst->notify(getGpioAction(entry.role), entry.pin);
|
||||
}
|
||||
break;
|
||||
case PinRole::OutputHighLocked:
|
||||
case PinRole::OutputHighUnlocked:
|
||||
case PinRole::OutputHighMotorBlocked:
|
||||
case PinRole::OutputHighRtoActive:
|
||||
case PinRole::OutputHighCmActive:
|
||||
case PinRole::OutputHighRtoOrCmActive:
|
||||
case PinRole::GeneralOutput:
|
||||
case PinRole::Ethernet:
|
||||
// ignore. This case should not occur since pins are configured as output
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio::isrOnTimer()
|
||||
{
|
||||
_inst->onTimer();
|
||||
}
|
||||
|
||||
void Gpio::init()
|
||||
{
|
||||
_inst->_triggerCount.reserve(_inst->availablePins().size());
|
||||
for(int i=0; i<_inst->availablePins().size(); i++)
|
||||
{
|
||||
_inst->_triggerCount.push_back(0);
|
||||
}
|
||||
|
||||
bool hasInputPin = false;
|
||||
|
||||
for(const auto& entry : _inst->_pinConfiguration)
|
||||
{
|
||||
const auto it = std::find(_inst->availablePins().begin(), _inst->availablePins().end(), entry.pin);
|
||||
@@ -42,48 +133,23 @@ void Gpio::init()
|
||||
switch(entry.role)
|
||||
{
|
||||
case PinRole::InputLock:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrLock, FALLING);
|
||||
break;
|
||||
case PinRole::InputUnlock:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrUnlock, FALLING);
|
||||
break;
|
||||
case PinRole::InputUnlatch:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrUnlatch, FALLING);
|
||||
break;
|
||||
case PinRole::InputLockNgo:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrLockNgo, FALLING);
|
||||
break;
|
||||
case PinRole::InputLockNgoUnlatch:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrLockNgoUnlatch, FALLING);
|
||||
break;
|
||||
case PinRole::InputElectricStrikeActuation:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrElectricStrikeActuation, FALLING);
|
||||
break;
|
||||
case PinRole::InputActivateRTO:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrActivateRTO, FALLING);
|
||||
break;
|
||||
case PinRole::InputActivateCM:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrActivateCM, FALLING);
|
||||
break;
|
||||
case PinRole::InputDeactivateRtoCm:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrDeactivateRtoCm, FALLING);
|
||||
break;
|
||||
case PinRole::InputDeactivateRTO:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrDeactivateRTO, FALLING);
|
||||
break;
|
||||
case PinRole::InputDeactivateCM:
|
||||
case PinRole::GeneralInputPullUp:
|
||||
pinMode(entry.pin, INPUT_PULLUP);
|
||||
attachInterrupt(entry.pin, isrDeactivateCM, FALLING);
|
||||
hasInputPin = true;
|
||||
break;
|
||||
case PinRole::GeneralInputPullDown:
|
||||
pinMode(entry.pin, INPUT_PULLDOWN);
|
||||
hasInputPin = true;
|
||||
break;
|
||||
case PinRole::OutputHighLocked:
|
||||
case PinRole::OutputHighUnlocked:
|
||||
@@ -94,19 +160,17 @@ void Gpio::init()
|
||||
case PinRole::GeneralOutput:
|
||||
pinMode(entry.pin, OUTPUT);
|
||||
break;
|
||||
case PinRole::GeneralInputPullDown:
|
||||
Gpio2Go::configurePin(entry.pin, PinMode::InputPullDown, InterruptMode::Change, 300);
|
||||
break;
|
||||
case PinRole::GeneralInputPullUp:
|
||||
Gpio2Go::configurePin(entry.pin, PinMode::InputPullup, InterruptMode::Change, 300);
|
||||
break;
|
||||
case PinRole::Ethernet:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Gpio2Go::subscribe(Gpio::inputCallback);
|
||||
if(hasInputPin)
|
||||
{
|
||||
_inst->timer = timerBegin(1000000);
|
||||
timerAttachInterrupt(_inst->timer, isrOnTimer);
|
||||
timerAlarm(_inst->timer, 100000, true, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +382,7 @@ const PinRole Gpio::getPinRole(const int &pin) const
|
||||
return PinRole::Disabled;
|
||||
}
|
||||
|
||||
String Gpio::getRoleDescription(PinRole role) const
|
||||
String Gpio::getRoleDescription(const PinRole& role) const
|
||||
{
|
||||
switch(role)
|
||||
{
|
||||
@@ -371,6 +435,53 @@ String Gpio::getRoleDescription(PinRole role) const
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GpioAction Gpio::getGpioAction(const PinRole &role) const
|
||||
{
|
||||
switch(role)
|
||||
{
|
||||
case PinRole::Disabled:
|
||||
return GpioAction::None;
|
||||
case PinRole::InputLock:
|
||||
return GpioAction::Lock;
|
||||
case PinRole::InputUnlock:
|
||||
return GpioAction::Unlock;
|
||||
case PinRole::InputUnlatch:
|
||||
return GpioAction::Unlatch;
|
||||
case PinRole::InputLockNgo:
|
||||
return GpioAction::LockNgo;
|
||||
case PinRole::InputLockNgoUnlatch:
|
||||
return GpioAction::LockNgoUnlatch;
|
||||
case PinRole::InputElectricStrikeActuation:
|
||||
return GpioAction::ElectricStrikeActuation;
|
||||
case PinRole::InputActivateRTO:
|
||||
return GpioAction::ActivateRTO;
|
||||
case PinRole::InputActivateCM:
|
||||
return GpioAction::ActivateCM;
|
||||
case PinRole::InputDeactivateRtoCm:
|
||||
return GpioAction::DeactivateRtoCm;
|
||||
case PinRole::InputDeactivateRTO:
|
||||
return GpioAction::DeactivateRTO;
|
||||
case PinRole::InputDeactivateCM:
|
||||
return GpioAction::DeactivateCM;
|
||||
|
||||
case PinRole::GeneralInputPullDown:
|
||||
case PinRole::GeneralInputPullUp:
|
||||
return GpioAction::GeneralInput;
|
||||
|
||||
case PinRole::GeneralOutput:
|
||||
case PinRole::Ethernet:
|
||||
case PinRole::OutputHighLocked:
|
||||
case PinRole::OutputHighUnlocked:
|
||||
case PinRole::OutputHighMotorBlocked:
|
||||
case PinRole::OutputHighRtoActive:
|
||||
case PinRole::OutputHighCmActive:
|
||||
case PinRole::OutputHighRtoOrCmActive:
|
||||
default:
|
||||
return GpioAction::None;
|
||||
}}
|
||||
|
||||
|
||||
void Gpio::getConfigurationText(String& text, const std::vector<PinEntry>& pinConfiguration, const String& linebreak) const
|
||||
{
|
||||
for(const auto& entry : pinConfiguration)
|
||||
@@ -403,93 +514,11 @@ void Gpio::notify(const GpioAction &action, const int& pin)
|
||||
}
|
||||
}
|
||||
|
||||
void Gpio::inputCallback(const int &pin)
|
||||
{
|
||||
_inst->notify(GpioAction::GeneralInput, pin);
|
||||
}
|
||||
|
||||
void Gpio::addCallback(std::function<void(const GpioAction&, const int&)> callback)
|
||||
{
|
||||
_callbacks.push_back(callback);
|
||||
}
|
||||
|
||||
void Gpio::isrLock()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::Lock, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrUnlock()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::Unlock, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrUnlatch()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::Unlatch, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrLockNgo()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::LockNgo, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrLockNgoUnlatch()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::LockNgoUnlatch, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrElectricStrikeActuation()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::ElectricStrikeActuation, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrActivateRTO()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::ActivateRTO, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrActivateCM()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::ActivateCM, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrDeactivateRtoCm()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::DeactivateRtoCm, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrDeactivateRTO()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::DeactivateRTO, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::isrDeactivateCM()
|
||||
{
|
||||
if((esp_timer_get_time() / 1000) < _debounceTs) return;
|
||||
_inst->notify(GpioAction::DeactivateCM, -1);
|
||||
_debounceTs = (esp_timer_get_time() / 1000) + _debounceTime;
|
||||
}
|
||||
|
||||
void Gpio::setPinOutput(const uint8_t& pin, const uint8_t& state)
|
||||
{
|
||||
digitalWrite(pin, state);
|
||||
@@ -523,3 +552,4 @@ void Gpio::migrateObsoleteSetting()
|
||||
restartEsp(RestartReason::GpioConfigurationUpdated);
|
||||
}
|
||||
|
||||
|
||||
|
||||
26
src/Gpio.h
26
src/Gpio.h
@@ -43,7 +43,8 @@ enum class GpioAction
|
||||
DeactivateRtoCm,
|
||||
DeactivateRTO,
|
||||
DeactivateCM,
|
||||
GeneralInput
|
||||
GeneralInput,
|
||||
None
|
||||
};
|
||||
|
||||
struct PinEntry
|
||||
@@ -70,7 +71,8 @@ public:
|
||||
const std::vector<int> getDisabledPins() const;
|
||||
const PinRole getPinRole(const int& pin) const;
|
||||
|
||||
String getRoleDescription(PinRole role) const;
|
||||
String getRoleDescription(const PinRole& role) const;
|
||||
|
||||
void getConfigurationText(String& text, const std::vector<PinEntry>& pinConfiguration, const String& linebreak = "\n") const;
|
||||
|
||||
const std::vector<PinRole>& getAllRoles() const;
|
||||
@@ -79,7 +81,9 @@ public:
|
||||
|
||||
private:
|
||||
void IRAM_ATTR notify(const GpioAction& action, const int& pin);
|
||||
static void inputCallback(const int & pin);
|
||||
void IRAM_ATTR onTimer();
|
||||
bool IRAM_ATTR isTriggered(const PinEntry& pinEntry);
|
||||
GpioAction IRAM_ATTR getGpioAction(const PinRole& role) const;
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
//Based on https://docs.espressif.com/projects/esp-idf/en/stable/esp32c3/api-reference/peripherals/gpio.html and https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf
|
||||
@@ -125,22 +129,14 @@ private:
|
||||
std::vector<PinEntry> _pinConfiguration;
|
||||
static const uint _debounceTime;
|
||||
|
||||
static void IRAM_ATTR isrLock();
|
||||
static void IRAM_ATTR isrUnlock();
|
||||
static void IRAM_ATTR isrUnlatch();
|
||||
static void IRAM_ATTR isrLockNgo();
|
||||
static void IRAM_ATTR isrLockNgoUnlatch();
|
||||
static void IRAM_ATTR isrElectricStrikeActuation();
|
||||
static void IRAM_ATTR isrActivateRTO();
|
||||
static void IRAM_ATTR isrActivateCM();
|
||||
static void IRAM_ATTR isrDeactivateRtoCm();
|
||||
static void IRAM_ATTR isrDeactivateRTO();
|
||||
static void IRAM_ATTR isrDeactivateCM();
|
||||
static void IRAM_ATTR isrOnTimer();
|
||||
|
||||
std::vector<std::function<void(const GpioAction&, const int&)>> _callbacks;
|
||||
|
||||
static Gpio* _inst;
|
||||
static int64_t _debounceTs;
|
||||
|
||||
std::vector<int8_t> _triggerCount;
|
||||
hw_timer_t* timer = nullptr;
|
||||
|
||||
Preferences* _preferences = nullptr;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user