Browse Source

Add support for GPIO open-drain output mode.

devsaurus 8 years ago
parent
commit
23137b4ed1
4 changed files with 30 additions and 16 deletions
  1. 9 7
      app/modules/gpio.c
  2. 16 5
      app/platform/platform.c
  3. 1 0
      app/platform/platform.h
  4. 4 4
      docs/en/modules/gpio.md

+ 9 - 7
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 }
 };
 

+ 16 - 5
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

+ 1 - 0
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

+ 4 - 4
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`