mirror of
https://github.com/martin-ger/esp_wifi_repeater.git
synced 2023-04-24 01:48:22 +03:00
Added GPIOs
This commit is contained in:
2
Makefile
2
Makefile
@@ -33,7 +33,7 @@ ESPPORT ?= /dev/ttyUSB0
|
||||
TARGET = app
|
||||
|
||||
# which modules (subdirectories) of the project to include in compiling
|
||||
MODULES = driver user mqtt
|
||||
MODULES = driver user mqtt easygpio
|
||||
EXTRA_INCDIR = $(BUILD_AREA)/esp-open-sdk/esp-open-lwip/include include
|
||||
#EXTRA_INCDIR = include
|
||||
|
||||
|
||||
343
easygpio/easygpio.c
Normal file
343
easygpio/easygpio.c
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* easygpio.c
|
||||
*
|
||||
* Copyright (c) 2015, eadf (https://github.com/eadf)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "easygpio.h"
|
||||
#include "gpio.h"
|
||||
#include "osapi.h"
|
||||
#include "ets_sys.h"
|
||||
|
||||
#define EASYGPIO_USE_GPIO_INPUT_GET
|
||||
|
||||
static void ICACHE_FLASH_ATTR
|
||||
gpio16_output_conf(void) {
|
||||
WRITE_PERI_REG(PAD_XPD_DCDC_CONF,
|
||||
(READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbcUL) | 0x1UL); // mux configuration for XPD_DCDC to output rtc_gpio0
|
||||
|
||||
WRITE_PERI_REG(RTC_GPIO_CONF,
|
||||
(READ_PERI_REG(RTC_GPIO_CONF) & 0xfffffffeUL) | 0x0UL); //mux configuration for out enable
|
||||
|
||||
WRITE_PERI_REG(RTC_GPIO_ENABLE,
|
||||
(READ_PERI_REG(RTC_GPIO_ENABLE) & 0xfffffffeUL) | 0x1UL); //out enable
|
||||
}
|
||||
|
||||
static void ICACHE_FLASH_ATTR
|
||||
gpio16_input_conf(void) {
|
||||
WRITE_PERI_REG(PAD_XPD_DCDC_CONF,
|
||||
(READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbcUL) | 0x1UL); // mux configuration for XPD_DCDC and rtc_gpio0 connection
|
||||
|
||||
WRITE_PERI_REG(RTC_GPIO_CONF,
|
||||
(READ_PERI_REG(RTC_GPIO_CONF) & 0xfffffffeUL) | 0x0UL); //mux configuration for out enable
|
||||
|
||||
WRITE_PERI_REG(RTC_GPIO_ENABLE,
|
||||
READ_PERI_REG(RTC_GPIO_ENABLE) & 0xfffffffeUL); //out disable
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of active pins in the gpioMask.
|
||||
*/
|
||||
uint8_t ICACHE_FLASH_ATTR
|
||||
easygpio_countBits(uint32_t gpioMask) {
|
||||
|
||||
uint8_t i=0;
|
||||
uint8_t numberOfPins=0;
|
||||
for (i=0; i<32; i++){
|
||||
numberOfPins += (gpioMask & BIT(i))?1:0;
|
||||
}
|
||||
return numberOfPins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the gpio name and func for a specific pin.
|
||||
*/
|
||||
bool ICACHE_FLASH_ATTR
|
||||
easygpio_getGPIONameFunc(uint8_t gpio_pin, uint32_t *gpio_name, uint8_t *gpio_func) {
|
||||
|
||||
if (gpio_pin == 6 || gpio_pin == 7 || gpio_pin == 8 || gpio_pin == 11 || gpio_pin >= 17) {
|
||||
os_printf("easygpio_getGPIONameFunc Error: There is no GPIO%d, check your code\n", gpio_pin);
|
||||
return false;
|
||||
}
|
||||
if (gpio_pin == 16) {
|
||||
os_printf("easygpio_getGPIONameFunc Error: GPIO16 does not have gpio_name and gpio_func\n");
|
||||
return false;
|
||||
}
|
||||
switch ( gpio_pin ) {
|
||||
case 0:
|
||||
*gpio_func = FUNC_GPIO0;
|
||||
*gpio_name = PERIPHS_IO_MUX_GPIO0_U;
|
||||
return true;
|
||||
case 1:
|
||||
*gpio_func = FUNC_GPIO1;
|
||||
*gpio_name = PERIPHS_IO_MUX_U0TXD_U;
|
||||
return true;
|
||||
case 2:
|
||||
*gpio_func = FUNC_GPIO2;
|
||||
*gpio_name = PERIPHS_IO_MUX_GPIO2_U;
|
||||
return true;
|
||||
case 3:
|
||||
*gpio_func = FUNC_GPIO3;
|
||||
*gpio_name = PERIPHS_IO_MUX_U0RXD_U;
|
||||
return true;
|
||||
case 4:
|
||||
*gpio_func = FUNC_GPIO4;
|
||||
*gpio_name = PERIPHS_IO_MUX_GPIO4_U;
|
||||
return true;
|
||||
case 5:
|
||||
*gpio_func = FUNC_GPIO5;
|
||||
*gpio_name = PERIPHS_IO_MUX_GPIO5_U;
|
||||
return true;
|
||||
case 9:
|
||||
*gpio_func = FUNC_GPIO9;
|
||||
*gpio_name = PERIPHS_IO_MUX_SD_DATA2_U;
|
||||
return true;
|
||||
case 10:
|
||||
*gpio_func = FUNC_GPIO10;
|
||||
*gpio_name = PERIPHS_IO_MUX_SD_DATA3_U;
|
||||
return true;
|
||||
case 12:
|
||||
*gpio_func = FUNC_GPIO12;
|
||||
*gpio_name = PERIPHS_IO_MUX_MTDI_U;
|
||||
return true;
|
||||
case 13:
|
||||
*gpio_func = FUNC_GPIO13;
|
||||
*gpio_name = PERIPHS_IO_MUX_MTCK_U;
|
||||
return true;
|
||||
case 14:
|
||||
*gpio_func = FUNC_GPIO14;
|
||||
*gpio_name = PERIPHS_IO_MUX_MTMS_U;
|
||||
return true;
|
||||
case 15:
|
||||
*gpio_func = FUNC_GPIO15;
|
||||
*gpio_name = PERIPHS_IO_MUX_MTDO_U;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pull up registers for a pin.
|
||||
*/
|
||||
static void ICACHE_FLASH_ATTR
|
||||
easygpio_setupPullsByName(uint32_t gpio_name, EasyGPIO_PullStatus pullStatus) {
|
||||
|
||||
if (EASYGPIO_PULLUP == pullStatus) {
|
||||
PIN_PULLUP_EN(gpio_name);
|
||||
} else {
|
||||
PIN_PULLUP_DIS(gpio_name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pull registers for a pin.
|
||||
*/
|
||||
bool ICACHE_FLASH_ATTR
|
||||
easygpio_pullMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus) {
|
||||
uint32_t gpio_name;
|
||||
uint8_t gpio_func;
|
||||
|
||||
if (!easygpio_getGPIONameFunc(gpio_pin, &gpio_name, &gpio_func) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
easygpio_setupPullsByName(gpio_name, pullStatus);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the 'gpio_pin' pin as a GPIO and sets the pull register for that pin.
|
||||
* 'pullStatus' has no effect on output pins or GPIO16
|
||||
*/
|
||||
bool ICACHE_FLASH_ATTR
|
||||
easygpio_pinMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, EasyGPIO_PinMode pinMode) {
|
||||
uint32_t gpio_name;
|
||||
uint8_t gpio_func;
|
||||
|
||||
if (16==gpio_pin) {
|
||||
// ignoring pull status on GPIO16 for now
|
||||
if (EASYGPIO_OUTPUT == pinMode) {
|
||||
gpio16_output_conf();
|
||||
} else {
|
||||
gpio16_input_conf();
|
||||
}
|
||||
return true;
|
||||
} else if (!easygpio_getGPIONameFunc(gpio_pin, &gpio_name, &gpio_func) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PIN_FUNC_SELECT(gpio_name, gpio_func);
|
||||
easygpio_setupPullsByName(gpio_name, pullStatus);
|
||||
|
||||
if (EASYGPIO_OUTPUT != pinMode) {
|
||||
GPIO_DIS_OUTPUT(GPIO_ID_PIN(gpio_pin));
|
||||
} else {
|
||||
// must enable the pin or else the WRITE_PERI_REG won't work
|
||||
gpio_output_set(0, 0, BIT(GPIO_ID_PIN(gpio_pin)),0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the 'gpio_pin' pin as a GPIO and sets the interrupt to trigger on that pin.
|
||||
* The 'interruptArg' is the function argument that will be sent to your interruptHandler
|
||||
*/
|
||||
bool ICACHE_FLASH_ATTR
|
||||
easygpio_attachInterrupt(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, void (*interruptHandler)(void *arg), void *interruptArg) {
|
||||
uint32_t gpio_name;
|
||||
uint8_t gpio_func;
|
||||
|
||||
if (gpio_pin == 16) {
|
||||
os_printf("easygpio_setupInterrupt Error: GPIO16 does not have interrupts\n");
|
||||
return false;
|
||||
}
|
||||
if (!easygpio_getGPIONameFunc(gpio_pin, &gpio_name, &gpio_func) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ETS_GPIO_INTR_ATTACH(interruptHandler, interruptArg);
|
||||
ETS_GPIO_INTR_DISABLE();
|
||||
|
||||
PIN_FUNC_SELECT(gpio_name, gpio_func);
|
||||
|
||||
easygpio_setupPullsByName(gpio_name, pullStatus);
|
||||
|
||||
// disable output
|
||||
GPIO_DIS_OUTPUT(gpio_pin);
|
||||
|
||||
gpio_register_set(GPIO_PIN_ADDR(gpio_pin), GPIO_PIN_INT_TYPE_SET(GPIO_PIN_INTR_DISABLE)
|
||||
| GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_DISABLE)
|
||||
| GPIO_PIN_SOURCE_SET(GPIO_AS_PIN_SOURCE));
|
||||
|
||||
//clear gpio14 status
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(gpio_pin));
|
||||
ETS_GPIO_INTR_ENABLE();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach the interrupt handler from the 'gpio_pin' pin.
|
||||
*/
|
||||
bool ICACHE_FLASH_ATTR
|
||||
easygpio_detachInterrupt(uint8_t gpio_pin) {
|
||||
|
||||
if (gpio_pin == 16) {
|
||||
os_printf("easygpio_setupInterrupt Error: GPIO16 does not have interrupts\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't know how to detach interrupt, yet.
|
||||
// Quick and dirty fix - just disable the interrupt
|
||||
gpio_pin_intr_state_set(GPIO_ID_PIN(gpio_pin), GPIO_PIN_INTR_DISABLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uniform way of setting GPIO output value. Handles GPIO 0-16.
|
||||
*
|
||||
* You can not rely on that this function will switch the gpio to an output like GPIO_OUTPUT_SET does.
|
||||
* Use easygpio_outputEnable() to change an input gpio to output mode.
|
||||
*/
|
||||
void
|
||||
easygpio_outputSet(uint8_t gpio_pin, uint8_t value) {
|
||||
if (16==gpio_pin) {
|
||||
WRITE_PERI_REG(RTC_GPIO_OUT,
|
||||
(READ_PERI_REG(RTC_GPIO_OUT) & 0xfffffffeUL) | (0x1UL & value));
|
||||
} else {
|
||||
#ifdef EASYGPIO_USE_GPIO_OUTPUT_SET
|
||||
GPIO_OUTPUT_SET(GPIO_ID_PIN(gpio_pin), value);
|
||||
#else
|
||||
if (value&1){
|
||||
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR, READ_PERI_REG(PERIPHS_GPIO_BASEADDR) | BIT(gpio_pin));
|
||||
} else {
|
||||
WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR, READ_PERI_REG(PERIPHS_GPIO_BASEADDR) & ~BIT(gpio_pin));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uniform way of getting GPIO input value. Handles GPIO 0-16.
|
||||
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
|
||||
* If you know that you won't be using GPIO16 then you'd better off by just using GPIO_INPUT_GET().
|
||||
*/
|
||||
uint8_t
|
||||
easygpio_inputGet(uint8_t gpio_pin) {
|
||||
if (16==gpio_pin) {
|
||||
return (READ_PERI_REG(RTC_GPIO_IN_DATA) & 1UL);
|
||||
} else {
|
||||
#ifdef EASYGPIO_USE_GPIO_INPUT_GET
|
||||
return GPIO_INPUT_GET(GPIO_ID_PIN(gpio_pin));
|
||||
#else
|
||||
// this does *not* work, maybe GPIO_IN_ADDRESS is the wrong address
|
||||
return ((GPIO_REG_READ(GPIO_IN_ADDRESS) > gpio_pin) & 1UL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uniform way of turning an output GPIO pin into input mode. Handles GPIO 0-16.
|
||||
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
|
||||
* This function does the same thing as GPIO_DIS_OUTPUT, but works on GPIO16 too.
|
||||
*/
|
||||
void easygpio_outputDisable(uint8_t gpio_pin) {
|
||||
if (16==gpio_pin) {
|
||||
WRITE_PERI_REG(RTC_GPIO_ENABLE,
|
||||
READ_PERI_REG(RTC_GPIO_ENABLE) & 0xfffffffeUL); //out disable
|
||||
} else {
|
||||
GPIO_DIS_OUTPUT(GPIO_ID_PIN(gpio_pin));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uniform way of turning an input GPIO pin into output mode. Handles GPIO 0-16.
|
||||
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
|
||||
*
|
||||
* This function:
|
||||
* - should only be used to convert a input pin into an output pin.
|
||||
* - is a little bit slower than easygpio_outputSet() so you should use that
|
||||
* function to just change output value.
|
||||
* - does the same thing as GPIO_OUTPUT_SET, but works on GPIO16 too.
|
||||
*/
|
||||
void easygpio_outputEnable(uint8_t gpio_pin, uint8_t value) {
|
||||
if (16==gpio_pin) {
|
||||
// write the value before flipping to output
|
||||
// - so we don't flash previous value for a few ns.
|
||||
WRITE_PERI_REG(RTC_GPIO_OUT,
|
||||
(READ_PERI_REG(RTC_GPIO_OUT) & 0xfffffffeUL) | (0x1UL & value));
|
||||
|
||||
WRITE_PERI_REG(RTC_GPIO_ENABLE,
|
||||
(READ_PERI_REG(RTC_GPIO_ENABLE) & 0xfffffffeUL) | 0x1UL); //out enable
|
||||
|
||||
} else {
|
||||
GPIO_OUTPUT_SET(GPIO_ID_PIN(gpio_pin), value);
|
||||
}
|
||||
}
|
||||
114
easygpio/easygpio.h
Normal file
114
easygpio/easygpio.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* easygpio.h
|
||||
*
|
||||
* Copyright (c) 2015, eadf (https://github.com/eadf)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef EASYGPIO_INCLUDE_EASYGPIO_EASYGPIO_H_
|
||||
#define EASYGPIO_INCLUDE_EASYGPIO_EASYGPIO_H_
|
||||
|
||||
#include "c_types.h"
|
||||
|
||||
typedef enum {
|
||||
EASYGPIO_INPUT=0,
|
||||
EASYGPIO_OUTPUT=1
|
||||
} EasyGPIO_PinMode;
|
||||
|
||||
typedef enum {
|
||||
EASYGPIO_PULLUP=3,
|
||||
EASYGPIO_NOPULL=4
|
||||
} EasyGPIO_PullStatus;
|
||||
|
||||
/**
|
||||
* Returns the gpio name and func for a specific pin.
|
||||
*/
|
||||
bool easygpio_getGPIONameFunc(uint8_t gpio_pin, uint32_t *gpio_name, uint8_t *gpio_func);
|
||||
|
||||
/**
|
||||
* Sets the 'gpio_pin' pin as a GPIO and sets the interrupt to trigger on that pin.
|
||||
* The 'interruptArg' is the function argument that will be sent to your interruptHandler
|
||||
* (this way you can several interrupts with one interruptHandler)
|
||||
*/
|
||||
bool easygpio_attachInterrupt(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, void (*interruptHandler)(void *arg), void *interruptArg);
|
||||
|
||||
/**
|
||||
* Deatach the interrupt handler from the 'gpio_pin' pin.
|
||||
*/
|
||||
bool easygpio_detachInterrupt(uint8_t gpio_pin);
|
||||
|
||||
/**
|
||||
* Returns the number of active pins in the gpioMask.
|
||||
*/
|
||||
uint8_t easygpio_countBits(uint32_t gpioMask);
|
||||
|
||||
/**
|
||||
* Sets the 'gpio_pin' pin as a GPIO and enables/disables the pull-up on that pin.
|
||||
* 'pullStatus' has no effect on output pins or GPIO16
|
||||
*/
|
||||
bool easygpio_pinMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus, EasyGPIO_PinMode pinMode);
|
||||
|
||||
/**
|
||||
* Enable or disable the internal pull up for a pin.
|
||||
*/
|
||||
bool easygpio_pullMode(uint8_t gpio_pin, EasyGPIO_PullStatus pullStatus);
|
||||
|
||||
/**
|
||||
* Uniform way of getting GPIO input value. Handles GPIO 0-16.
|
||||
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
|
||||
* If you know that you won't be using GPIO16 then you'd better off by just using GPIO_INPUT_GET().
|
||||
*/
|
||||
uint8_t easygpio_inputGet(uint8_t gpio_pin);
|
||||
|
||||
/**
|
||||
* Uniform way of setting GPIO output value. Handles GPIO 0-16.
|
||||
*
|
||||
* You can not rely on that this function will switch the gpio to an output like GPIO_OUTPUT_SET does.
|
||||
* Use easygpio_outputEnable() to change an input gpio to output mode.
|
||||
*/
|
||||
void easygpio_outputSet(uint8_t gpio_pin, uint8_t value);
|
||||
|
||||
/**
|
||||
* Uniform way of turning an output GPIO pin into input mode. Handles GPIO 0-16.
|
||||
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
|
||||
* This function does the same thing as GPIO_DIS_OUTPUT, but works on GPIO16 too.
|
||||
*/
|
||||
void easygpio_outputDisable(uint8_t gpio_pin);
|
||||
|
||||
/**
|
||||
* Uniform way of turning an input GPIO pin into output mode. Handles GPIO 0-16.
|
||||
* The pin must be initiated with easygpio_pinMode() so that the pin mux is setup as a gpio in the first place.
|
||||
*
|
||||
* This function:
|
||||
* - should only be used to convert a input pin into an output pin.
|
||||
* - is a little bit slower than easygpio_outputSet() so you should use that
|
||||
* function to just change output value.
|
||||
* - does the same thing as GPIO_OUTPUT_SET, but works on GPIO16 too.
|
||||
*/
|
||||
void easygpio_outputEnable(uint8_t gpio_pin, uint8_t value);
|
||||
|
||||
#endif /* EASYGPIO_INCLUDE_EASYGPIO_EASYGPIO_H_ */
|
||||
@@ -39,6 +39,8 @@ uint8_t mac[6];
|
||||
os_sprintf(config->mqtt_id,"%s_%2x%2x%2x", MQTT_ID, mac[3], mac[4], mac[5]);
|
||||
os_sprintf(config->mqtt_prefix,"%s/%s/system", MQTT_PREFIX, config->mqtt_id);
|
||||
os_sprintf(config->mqtt_command_topic,"%s/%s/%s", MQTT_PREFIX, config->mqtt_id, "command");
|
||||
os_sprintf(config->mqtt_gpio_out_topic,"%s/%s/%s", MQTT_PREFIX, config->mqtt_id, "switch");
|
||||
config->gpio_out_status = 0;
|
||||
config->mqtt_interval = MQTT_REPORT_INTERVAL;
|
||||
config->mqtt_topic_mask = 0xffff;
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ typedef struct
|
||||
uint8_t mqtt_id[32]; // MQTT clientId
|
||||
uint8_t mqtt_prefix[64]; // Topic-prefix
|
||||
uint8_t mqtt_command_topic[64]; // Topic on which commands are received, "none" if not subscibed
|
||||
uint8_t mqtt_gpio_out_topic[64]; // Topic on which the status of the gpio_out pin can be set
|
||||
bool gpio_out_status; // Initial status of the gpio_out pin
|
||||
|
||||
uint32_t mqtt_interval; // Interval in secs for status messages, 0 means no messages
|
||||
uint16_t mqtt_topic_mask;// Mask for active topics
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef _USER_CONFIG_
|
||||
#define _USER_CONFIG_
|
||||
|
||||
typedef enum {SIG_DO_NOTHING=0, SIG_START_SERVER=1, SIG_SEND_DATA, SIG_UART0, SIG_CONSOLE_RX, SIG_CONSOLE_TX, SIG_PACKET } USER_SIGNALS;
|
||||
typedef enum {SIG_DO_NOTHING=0, SIG_START_SERVER=1, SIG_SEND_DATA, SIG_UART0, SIG_CONSOLE_RX, SIG_CONSOLE_TX, SIG_PACKET, SIG_GPIO_INT } USER_SIGNALS;
|
||||
|
||||
#define WIFI_SSID "ssid"
|
||||
#define WIFI_PASSWORD "password"
|
||||
@@ -19,15 +19,9 @@ typedef enum {SIG_DO_NOTHING=0, SIG_START_SERVER=1, SIG_SEND_DATA, SIG_UART0, SI
|
||||
#define MAX_CON_CMD_SIZE 80
|
||||
|
||||
//
|
||||
// Define this if you have a status LED connected to GPIO LED_NO
|
||||
// Define this if you have a status LED connected to a GPIO pin
|
||||
//
|
||||
#define STATUS_LED 1
|
||||
#define LED_NO 2
|
||||
|
||||
// Select the GPIO init function according to your selected GPIO
|
||||
//#define SET_LED_GPIO PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1)
|
||||
#define SET_LED_GPIO PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2)
|
||||
//#define SET_LED_GPIO PIN_FUNC_SELECT (PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO4)
|
||||
#define STATUS_LED_GIPO 13
|
||||
|
||||
//
|
||||
// Define this to support the "scan" command for AP search
|
||||
@@ -38,7 +32,7 @@ typedef enum {SIG_DO_NOTHING=0, SIG_START_SERVER=1, SIG_SEND_DATA, SIG_UART0, SI
|
||||
// Define this to support the "sleep" command for power management and deep sleep
|
||||
// Requires a connection of GPIO16 and RST (probably not availabe on ESP01 modules)
|
||||
//
|
||||
#define ALLOW_SLEEP 1
|
||||
//#define ALLOW_SLEEP 1
|
||||
|
||||
//
|
||||
// Define this if you want to have access to the config console via TCP.
|
||||
@@ -78,4 +72,10 @@ typedef enum {SIG_DO_NOTHING=0, SIG_START_SERVER=1, SIG_SEND_DATA, SIG_UART0, SI
|
||||
#define MQTT_ID "ESPRouter"
|
||||
#define MQTT_REPORT_INTERVAL 15 /*seconds*/
|
||||
|
||||
// Define this if you want to get messages about GPIO pin status changes
|
||||
#define USER_GPIO_IN 0
|
||||
|
||||
// Define this if you want to set an output signal
|
||||
#define USER_GPIO_OUT 12
|
||||
|
||||
#endif
|
||||
|
||||
149
user/user_main.c
149
user/user_main.c
@@ -21,10 +21,16 @@
|
||||
#include "config_flash.h"
|
||||
#include "sys_time.h"
|
||||
|
||||
#include "easygpio.h"
|
||||
|
||||
#ifdef REMOTE_MONITORING
|
||||
#include "pcap.h"
|
||||
#endif
|
||||
|
||||
#ifdef MQTT_CLIENT
|
||||
#include "mqtt.h"
|
||||
#endif
|
||||
|
||||
uint32_t readvdd33(void);
|
||||
uint32_t Vdd;
|
||||
|
||||
@@ -59,7 +65,6 @@ void ICACHE_FLASH_ATTR user_set_softap_wifi_config(void);
|
||||
void ICACHE_FLASH_ATTR user_set_softap_ip_config(void);
|
||||
|
||||
#ifdef MQTT_CLIENT
|
||||
#include "mqtt.h"
|
||||
|
||||
#define MQTT_TOPIC_RESPONSE 0x0001
|
||||
#define MQTT_TOPIC_IP 0x0002
|
||||
@@ -75,6 +80,8 @@ void ICACHE_FLASH_ATTR user_set_softap_ip_config(void);
|
||||
#define MQTT_TOPIC_BPSIN 0x0800
|
||||
#define MQTT_TOPIC_BPSOUT 0x1000
|
||||
#define MQTT_TOPIC_NOSTATIONS 0x2000
|
||||
#define MQTT_TOPIC_GPIOIN 0x4000
|
||||
#define MQTT_TOPIC_GPIOOUT 0x8000
|
||||
|
||||
MQTT_Client mqttClient;
|
||||
bool mqtt_enabled;
|
||||
@@ -111,6 +118,11 @@ uint8_t ip_str[16];
|
||||
if (os_strcmp(config.mqtt_command_topic, "none") != 0) {
|
||||
MQTT_Subscribe(client, config.mqtt_command_topic, 0);
|
||||
}
|
||||
#ifdef USER_GPIO_OUT
|
||||
if (os_strcmp(config.mqtt_command_topic, "none") != 0) {
|
||||
MQTT_Subscribe(client, config.mqtt_gpio_out_topic, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void ICACHE_FLASH_ATTR mqttDisconnectedCb(uint32_t *args)
|
||||
@@ -136,6 +148,17 @@ static void ICACHE_FLASH_ATTR mqttDataCb(uint32_t *args, const char* topic, uint
|
||||
system_os_post(0, SIG_CONSOLE_RX, 0);
|
||||
return;
|
||||
}
|
||||
#ifdef USER_GPIO_OUT
|
||||
if (topic_len == os_strlen(config.mqtt_gpio_out_topic) && os_strncmp(topic, config.mqtt_gpio_out_topic, topic_len) == 0) {
|
||||
if (data_len > 0 && data[0] == '0')
|
||||
config.gpio_out_status = 0;
|
||||
else
|
||||
config.gpio_out_status = 1;
|
||||
easygpio_outputSet(USER_GPIO_OUT, config.gpio_out_status);
|
||||
mqtt_publish_int(MQTT_TOPIC_GPIOOUT, "GpioOut", "%d", (uint32_t)config.gpio_out_status);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
#endif /* MQTT_CLIENT */
|
||||
@@ -291,8 +314,8 @@ err_t ICACHE_FLASH_ATTR my_input_ap (struct pbuf *p, struct netif *inp) {
|
||||
Bytes_in += p->tot_len;
|
||||
Packets_in++;
|
||||
|
||||
#ifdef STATUS_LED
|
||||
GPIO_OUTPUT_SET (LED_NO, 1);
|
||||
#ifdef STATUS_LED_GIPO
|
||||
GPIO_OUTPUT_SET (STATUS_LED_GIPO, 1);
|
||||
#endif
|
||||
|
||||
#ifdef REMOTE_MONITORING
|
||||
@@ -318,8 +341,8 @@ err_t ICACHE_FLASH_ATTR my_output_ap (struct netif *outp, struct pbuf *p) {
|
||||
Bytes_out += p->tot_len;
|
||||
Packets_out++;
|
||||
|
||||
#ifdef STATUS_LED
|
||||
GPIO_OUTPUT_SET (LED_NO, 0);
|
||||
#ifdef STATUS_LED_GIPO
|
||||
GPIO_OUTPUT_SET (STATUS_LED_GIPO, 0);
|
||||
#endif
|
||||
|
||||
#ifdef REMOTE_MONITORING
|
||||
@@ -578,6 +601,10 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
|
||||
os_sprintf(response, "System uptime: %d:%02d:%02d\r\nPower supply: %d.%03d V\r\n",
|
||||
time/3600, (time%3600)/60, time%60, Vdd/1000, Vdd%1000);
|
||||
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
|
||||
#ifdef USER_GPIO_OUT
|
||||
os_sprintf(response, "GPIO output status: %d\r\n", config.gpio_out_status);
|
||||
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
|
||||
#endif
|
||||
os_sprintf(response, "%d KiB in (%d packets)\r\n%d KiB out (%d packets)\r\n",
|
||||
(uint32_t)(Bytes_in/1024), Packets_in,
|
||||
(uint32_t)(Bytes_out/1024), Packets_out);
|
||||
@@ -611,8 +638,8 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
|
||||
os_sprintf(response, "MQTT host: %s\r\nMQTT port: %d\r\nMQTT user: %s\r\nMQTT password: %s\r\n",
|
||||
config.mqtt_host, config.mqtt_port, config.mqtt_user, config.locked?"***":(char*)config.mqtt_password);
|
||||
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
|
||||
os_sprintf(response, "MQTT id: %s\r\nMQTT prefix: %s\r\nMQTT command topic: %s\r\nMQTT interval: %d s\r\nMQTT mask: %04x\r\n",
|
||||
config.mqtt_id, config.mqtt_prefix, config.mqtt_command_topic, config.mqtt_interval, config.mqtt_topic_mask);
|
||||
os_sprintf(response, "MQTT id: %s\r\nMQTT prefix: %s\r\nMQTT command topic: %s\r\nMQTT gpio_out topic: %s\r\nMQTT interval: %d s\r\nMQTT mask: %04x\r\n",
|
||||
config.mqtt_id, config.mqtt_prefix, config.mqtt_command_topic, config.mqtt_gpio_out_topic, config.mqtt_interval, config.mqtt_topic_mask);
|
||||
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
|
||||
|
||||
goto command_handled_2;
|
||||
@@ -1018,7 +1045,27 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
|
||||
os_sprintf(response, "MQTT topic mask set to %4x\r\n", val);
|
||||
goto command_handled;
|
||||
}
|
||||
#ifdef USER_GPIO_OUT
|
||||
if (strcmp(tokens[1], "mqtt_gpio_out_topic") == 0)
|
||||
{
|
||||
os_strncpy(config.mqtt_gpio_out_topic, tokens[2], 64);
|
||||
config.mqtt_gpio_out_topic[63] = 0;
|
||||
os_sprintf(response, "MQTT gpio_out topic set\r\n");
|
||||
goto command_handled;
|
||||
}
|
||||
#endif
|
||||
#endif /* MQTT_CLIENT */
|
||||
|
||||
#ifdef USER_GPIO_OUT
|
||||
if (strcmp(tokens[1], "gpio_out") == 0)
|
||||
{
|
||||
config.gpio_out_status = atoi(tokens[2]);
|
||||
easygpio_outputSet(USER_GPIO_OUT, config.gpio_out_status);
|
||||
mqtt_publish_int(MQTT_TOPIC_GPIOOUT, "GpioOut", "%d", (uint32_t)config.gpio_out_status);
|
||||
os_sprintf(response, "GPIO out set to %d\r\n", config.gpio_out_status);
|
||||
goto command_handled;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1093,8 +1140,8 @@ uint64_t t_new;
|
||||
uint32_t t_diff;
|
||||
|
||||
toggle = !toggle;
|
||||
#ifdef STATUS_LED
|
||||
GPIO_OUTPUT_SET (LED_NO, toggle && connected);
|
||||
#ifdef STATUS_LED_GIPO
|
||||
GPIO_OUTPUT_SET (STATUS_LED_GIPO, toggle && connected);
|
||||
#endif
|
||||
// Power measurement
|
||||
// Measure Vdd every second, sliding mean over the last 16 secs
|
||||
@@ -1129,6 +1176,9 @@ uint32_t t_diff;
|
||||
mqtt_publish_int(MQTT_TOPIC_NOSTATIONS, "NoStations", "%d", config.ap_on?wifi_softap_get_station_num():0);
|
||||
mqtt_publish_int(MQTT_TOPIC_BPSIN, "Bpsin", "%d", (uint32_t)(Bytes_in-Bytes_in_last)/t_diff);
|
||||
mqtt_publish_int(MQTT_TOPIC_BPSOUT, "Bpsout", "%d", (uint32_t)(Bytes_out-Bytes_out_last)/t_diff);
|
||||
#ifdef USER_GPIO_OUT
|
||||
mqtt_publish_int(MQTT_TOPIC_GPIOOUT, "GpioOut", "%d", (uint32_t)config.gpio_out_status);
|
||||
#endif
|
||||
|
||||
t_old = t_new;
|
||||
Bytes_in_last = Bytes_in;
|
||||
@@ -1179,6 +1229,16 @@ static void ICACHE_FLASH_ATTR user_procTask(os_event_t *events)
|
||||
break;
|
||||
#endif
|
||||
*/
|
||||
#ifdef MQTT_CLIENT
|
||||
#ifdef USER_GPIO_IN
|
||||
case SIG_GPIO_INT:
|
||||
{
|
||||
mqtt_publish_int(MQTT_TOPIC_GPIOIN, "GpioIn", "%d", (uint32_t)events->par);
|
||||
//os_printf("GPIO %d %d\r\n", (uint32_t)events->par, easygpio_inputGet(USER_GPIO_IN));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
case SIG_DO_NOTHING:
|
||||
default:
|
||||
// Intentionally ignoring other signals
|
||||
@@ -1346,6 +1406,44 @@ void ICACHE_FLASH_ATTR user_set_station_config(void)
|
||||
wifi_station_set_auto_connect(config.auto_connect != 0);
|
||||
}
|
||||
|
||||
#ifdef MQTT_CLIENT
|
||||
#ifdef USER_GPIO_IN
|
||||
static os_timer_t inttimer;
|
||||
|
||||
void ICACHE_FLASH_ATTR int_timer_func(void *arg){
|
||||
mqtt_publish_int(MQTT_TOPIC_GPIOIN, "GpioIn", "%d", easygpio_inputGet(USER_GPIO_IN));
|
||||
//os_printf("GPIO %d %d\r\n", (uint32_t)arg, easygpio_inputGet(USER_GPIO_IN));
|
||||
|
||||
// Reactivate interrupts for GPIO
|
||||
gpio_pin_intr_state_set(GPIO_ID_PIN(USER_GPIO_IN), GPIO_PIN_INTR_ANYEDGE);
|
||||
}
|
||||
|
||||
// Interrupt handler - this function will be executed on any edge of USER_GPIO_IN
|
||||
LOCAL void gpio_intr_handler(void *dummy)
|
||||
{
|
||||
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
|
||||
|
||||
if (gpio_status & BIT(USER_GPIO_IN)) {
|
||||
|
||||
// Disable interrupt for GPIO
|
||||
gpio_pin_intr_state_set(GPIO_ID_PIN(USER_GPIO_IN), GPIO_PIN_INTR_DISABLE);
|
||||
|
||||
// Post it to the main task
|
||||
//system_os_post(0, SIG_GPIO_INT, (ETSParam) easygpio_inputGet(USER_GPIO_IN));
|
||||
|
||||
// Clear interrupt status for GPIO
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(USER_GPIO_IN));
|
||||
|
||||
// Start the timer
|
||||
os_timer_setfn(&inttimer, int_timer_func, easygpio_inputGet(USER_GPIO_IN));
|
||||
os_timer_arm(&inttimer, 50, 0);
|
||||
|
||||
// Reactivate interrupts foR GPIO
|
||||
//gpio_pin_intr_state_set(GPIO_ID_PIN(USER_GPIO_IN), GPIO_PIN_INTR_ANYEDGE);
|
||||
}
|
||||
}
|
||||
#endif /* USER_GPIO_IN */
|
||||
#endif /* MQTT_CLIENT */
|
||||
|
||||
void ICACHE_FLASH_ATTR user_init()
|
||||
{
|
||||
@@ -1365,14 +1463,7 @@ void ICACHE_FLASH_ATTR user_init()
|
||||
|
||||
os_printf("\r\n\r\nWiFi Repeater V1.3 starting\r\n");
|
||||
|
||||
#ifdef STATUS_LED
|
||||
// Config GPIO pin as output
|
||||
if (LED_NO == 1) system_set_os_print(0);
|
||||
SET_LED_GPIO;
|
||||
GPIO_OUTPUT_SET (LED_NO, 0);
|
||||
#endif
|
||||
|
||||
// Load WiFi-config
|
||||
// Load config
|
||||
if (config_load(&config)== 0) {
|
||||
// valid config in FLASH, can read portmap table
|
||||
blob_load(0, (uint32_t *)ip_portmap_table, sizeof(struct portmap_table) * IP_PORTMAP_MAX);
|
||||
@@ -1382,6 +1473,28 @@ void ICACHE_FLASH_ATTR user_init()
|
||||
blob_zero(0, sizeof(struct portmap_table) * IP_PORTMAP_MAX);
|
||||
}
|
||||
|
||||
#ifdef STATUS_LED_GIPO
|
||||
// Config GPIO pin as output
|
||||
#if (STATUS_LED_GIPO == 1)
|
||||
// Disable output if serial pin is used as status LED
|
||||
system_set_os_print(0);
|
||||
#endif
|
||||
easygpio_pinMode(STATUS_LED_GIPO, EASYGPIO_NOPULL, EASYGPIO_OUTPUT);
|
||||
GPIO_OUTPUT_SET (STATUS_LED_GIPO, 0);
|
||||
#endif
|
||||
|
||||
#ifdef MQTT_CLIENT
|
||||
#ifdef USER_GPIO_IN
|
||||
easygpio_pinMode(USER_GPIO_IN, EASYGPIO_PULLUP, EASYGPIO_INPUT);
|
||||
easygpio_attachInterrupt(USER_GPIO_IN, EASYGPIO_PULLUP, gpio_intr_handler, NULL);
|
||||
gpio_pin_intr_state_set(GPIO_ID_PIN(USER_GPIO_IN), GPIO_PIN_INTR_ANYEDGE);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USER_GPIO_OUT
|
||||
easygpio_pinMode(USER_GPIO_OUT, EASYGPIO_NOPULL, EASYGPIO_OUTPUT);
|
||||
easygpio_outputSet(USER_GPIO_OUT, config.gpio_out_status);
|
||||
#endif
|
||||
|
||||
// Configure the AP and start it, if required
|
||||
|
||||
if (config.ap_on) {
|
||||
@@ -1450,6 +1563,6 @@ void ICACHE_FLASH_ATTR user_init()
|
||||
system_update_cpu_freq(config.clock_speed);
|
||||
|
||||
//Start task
|
||||
system_os_task(user_procTask, user_procTaskPrio,user_procTaskQueue, user_procTaskQueueLen);
|
||||
system_os_task(user_procTask, user_procTaskPrio, user_procTaskQueue, user_procTaskQueueLen);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user