diff --git a/app/modules/gpio.c b/app/modules/gpio.c index 9991c908..43fef9a5 100644 --- a/app/modules/gpio.c +++ b/app/modules/gpio.c @@ -12,6 +12,7 @@ #define PULLUP PLATFORM_GPIO_PULLUP #define FLOAT PLATFORM_GPIO_FLOAT #define OUTPUT PLATFORM_GPIO_OUTPUT +#define OPENDRAIN PLATFORM_GPIO_OPENDRAIN #define INPUT PLATFORM_GPIO_INPUT #define INTERRUPT PLATFORM_GPIO_INT #define HIGH PLATFORM_GPIO_HIGH @@ -93,7 +94,7 @@ static int lgpio_mode( lua_State* L ) unsigned pullup = luaL_optinteger( L, 3, FLOAT ); luaL_argcheck(L, platform_gpio_exists(pin) && (mode!=INTERRUPT || pin>0), 1, "Invalid pin"); - luaL_argcheck(L, mode==OUTPUT || mode==INPUT + luaL_argcheck(L, mode==OUTPUT || mode==OPENDRAIN || mode==INPUT #ifdef GPIO_INTERRUPT_ENABLE || mode==INTERRUPT #endif @@ -203,12 +204,13 @@ static const LUA_REG_TYPE gpio_map[] = { { LSTRKEY( "trig" ), LFUNCVAL( lgpio_trig ) }, { LSTRKEY( "INT" ), LNUMVAL( INTERRUPT ) }, #endif - { LSTRKEY( "OUTPUT" ), LNUMVAL( OUTPUT ) }, - { LSTRKEY( "INPUT" ), LNUMVAL( INPUT ) }, - { LSTRKEY( "HIGH" ), LNUMVAL( HIGH ) }, - { LSTRKEY( "LOW" ), LNUMVAL( LOW ) }, - { LSTRKEY( "FLOAT" ), LNUMVAL( FLOAT ) }, - { LSTRKEY( "PULLUP" ), LNUMVAL( PULLUP ) }, + { LSTRKEY( "OUTPUT" ), LNUMVAL( OUTPUT ) }, + { LSTRKEY( "OPENDRAIN" ), LNUMVAL( OPENDRAIN ) }, + { LSTRKEY( "INPUT" ), LNUMVAL( INPUT ) }, + { LSTRKEY( "HIGH" ), LNUMVAL( HIGH ) }, + { LSTRKEY( "LOW" ), LNUMVAL( LOW ) }, + { LSTRKEY( "FLOAT" ), LNUMVAL( FLOAT ) }, + { LSTRKEY( "PULLUP" ), LNUMVAL( PULLUP ) }, { LNILKEY, LNILVAL } }; diff --git a/app/platform/platform.c b/app/platform/platform.c index e7bb32ad..69089480 100755 --- a/app/platform/platform.c +++ b/app/platform/platform.c @@ -60,7 +60,7 @@ uint8_t platform_key_led( uint8_t level){ /* * Set GPIO mode to output. Optionally in RAM helper because interrupts are dsabled */ -static void NO_INTR_CODE set_gpio_no_interrupt(uint8 pin) { +static void NO_INTR_CODE set_gpio_no_interrupt(uint8 pin, uint8_t push_pull) { unsigned pnum = pin_num[pin]; ETS_GPIO_INTR_DISABLE(); #ifdef GPIO_INTERRUPT_ENABLE @@ -71,9 +71,17 @@ static void NO_INTR_CODE set_gpio_no_interrupt(uint8 pin) { gpio_pin_intr_state_set(GPIO_ID_PIN(pnum), GPIO_PIN_INTR_DISABLE); //clear interrupt status GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(pnum)); - GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pnum)), - GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pnum))) & - (~ GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))); //disable open drain; + + // configure push-pull vs open-drain + if (push_pull) { + GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pnum)), + GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pnum))) & + (~ GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))); //disable open drain; + } else { + GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pnum)), + GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pnum))) | + GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //enable open drain; + } ETS_GPIO_INTR_ENABLE(); } @@ -124,7 +132,10 @@ int platform_gpio_mode( unsigned pin, unsigned mode, unsigned pull ) GPIO_DIS_OUTPUT(pin_num[pin]); /* run on */ case PLATFORM_GPIO_OUTPUT: - set_gpio_no_interrupt(pin); + set_gpio_no_interrupt(pin, TRUE); + break; + case PLATFORM_GPIO_OPENDRAIN: + set_gpio_no_interrupt(pin, FALSE); break; #ifdef GPIO_INTERRUPT_ENABLE diff --git a/app/platform/platform.h b/app/platform/platform.h index 1835bdb9..1b25f29e 100644 --- a/app/platform/platform.h +++ b/app/platform/platform.h @@ -32,6 +32,7 @@ uint8_t platform_key_led( uint8_t level); #define PLATFORM_GPIO_INT 2 #define PLATFORM_GPIO_OUTPUT 1 +#define PLATFORM_GPIO_OPENDRAIN 3 #define PLATFORM_GPIO_INPUT 0 #define PLATFORM_GPIO_HIGH 1 diff --git a/docs/en/modules/gpio.md b/docs/en/modules/gpio.md index d76e05c4..63b06b78 100644 --- a/docs/en/modules/gpio.md +++ b/docs/en/modules/gpio.md @@ -20,20 +20,20 @@ If not using a NodeMCU dev kit, please refer to the below GPIO pin maps for the | 5 | GPIO14 | 12 | GPIO10 | | 6 | GPIO12 | | | -** [*] D0(GPIO16) can only be used as gpio read/write. No interrupt support. No pwm/i2c/ow support. ** +** [*] D0(GPIO16) can only be used as gpio read/write. No support for open-drain/interrupt/pwm/i2c/ow. ** ## gpio.mode() -Initialize pin to GPIO mode, set the pin in/out direction, and optional internal pullup. +Initialize pin to GPIO mode, set the pin in/out direction, and optional internal weak pull-up. #### Syntax `gpio.mode(pin, mode [, pullup])` #### Parameters - `pin` pin to configure, IO index -- `mode` one of gpio.OUTPUT or gpio.INPUT, or gpio.INT(interrupt mode) -- `pullup` gpio.PULLUP or gpio.FLOAT; default is gpio.FLOAT +- `mode` one of gpio.OUTPUT, gpio.OPENDRAIN, gpio.INPUT, or gpio.INT (interrupt mode) +- `pullup` gpio.PULLUP enables the weak pull-up resistor; default is gpio.FLOAT #### Returns `nil`