From 5595ca35cb23f3c4dd670dbc811cce355ce94898 Mon Sep 17 00:00:00 2001 From: TerryE Date: Tue, 8 Mar 2016 17:38:21 +0000 Subject: [PATCH 1/2] Small bugfix to GPIO.c -- Oops! --- app/modules/gpio.c | 13 +++++++++---- docs/en/modules/gpio.md | 13 ++++++++----- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/app/modules/gpio.c b/app/modules/gpio.c index 9991c908..e67838a3 100644 --- a/app/modules/gpio.c +++ b/app/modules/gpio.c @@ -62,22 +62,27 @@ static void gpio_intr_callback_task (task_param_t param, uint8 priority) static int lgpio_trig( lua_State* L ) { unsigned pin = luaL_checkinteger( L, 1 ); - static const char * const opts[] = {"", "up", "down", "both", "low", "high"}; + int old_pin_ref = gpio_cb_ref[pin]; + static const char * const opts[] = {"none", "up", "down", "both", "low", "high", NULL}; static const int opts_type[] = { GPIO_PIN_INTR_DISABLE, GPIO_PIN_INTR_POSEDGE, GPIO_PIN_INTR_NEGEDGE, GPIO_PIN_INTR_ANYEDGE, GPIO_PIN_INTR_LOLEVEL, GPIO_PIN_INTR_HILEVEL }; - int type = opts_type[luaL_checkoption(L, 2, "", opts)]; - luaL_argcheck(L, platform_gpio_exists(pin) && pin>0, 1, "Invalid interrupt pin"); + int type = opts_type[luaL_checkoption(L, 2, "none", opts)]; if (type != GPIO_PIN_INTR_DISABLE) { int cbtype = lua_type(L, 3); - luaL_argcheck(L, cbtype == LUA_TFUNCTION || cbtype == LUA_TLIGHTFUNCTION, 3, + luaL_argcheck(L, cbtype == LUA_TFUNCTION || cbtype == LUA_TLIGHTFUNCTION, 3, "invalid callback type"); lua_pushvalue(L, 3); // copy argument (func) to the top of stack gpio_cb_ref[pin] = luaL_ref(L, LUA_REGISTRYINDEX); + } else { + gpio_cb_ref[pin] = LUA_NOREF; } + + if(old_pin_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, old_pin_ref); + NODE_DBG("Pin data: %d %d %08x, %d %d %d, %08x\n", pin, type, pin_mux[pin], pin_num[pin], pin_func[pin], pin_int_type[pin], gpio_cb_ref[pin]); platform_gpio_intr_init(pin, type); diff --git a/docs/en/modules/gpio.md b/docs/en/modules/gpio.md index d76e05c4..d22af361 100644 --- a/docs/en/modules/gpio.md +++ b/docs/en/modules/gpio.md @@ -98,18 +98,18 @@ gpio.serout(1,1,{8,18},8) -- serial 30% pwm 38k, lasts 8 cycles ## gpio.trig() -Establish a callback function to run on interrupt for a pin. - -There is currently no support for unregistering the callback. +Establish or clear a callback function to run on interrupt for a pin. This function is not available if GPIO_INTERRUPT_ENABLE was undefined at compile time. #### Syntax -`gpio.trig(pin, type [, function(level)])` +`gpio.trig(pin, [type [, function(level)]})` #### Parameters - `pin` **1~12**, IO index, pin D0 does not support interrupt. -- `type` "up", "down", "both", "low", "high", which represent rising edge, falling edge, both edge, low level, high level trig mode correspondingly. +- `type` "up", "down", "both", "low", "high", which represent rising edge, falling edge, both edge, +low level, high level trig mode correspondingly. If the type is "none" or omitted then the +callback function is removed and the interrupt disabled. - `function(level)` callback function when triggered. The gpio level is the param. Use previous callback function if undefined here. #### Returns @@ -131,6 +131,9 @@ function pin1cb(level) end gpio.trig(pin, "down", pin1cb) +``` +```Lua +gpio.trig(4, 'none') -- remove any existing trigger ``` #### See also [`gpio.mode()`](#gpiomode) From 20465dd30f97052a2c95597425d417ace16e7cea Mon Sep 17 00:00:00 2001 From: TerryE Date: Mon, 14 Mar 2016 01:11:09 +0000 Subject: [PATCH 2/2] Updates to gpio.c and documentation to reflect review comments --- app/modules/gpio.c | 27 +++++++++++++++++++-------- docs/en/modules/gpio.md | 41 ++++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/app/modules/gpio.c b/app/modules/gpio.c index e67838a3..13e99aa5 100644 --- a/app/modules/gpio.c +++ b/app/modules/gpio.c @@ -62,25 +62,36 @@ static void gpio_intr_callback_task (task_param_t param, uint8 priority) static int lgpio_trig( lua_State* L ) { unsigned pin = luaL_checkinteger( L, 1 ); - int old_pin_ref = gpio_cb_ref[pin]; static const char * const opts[] = {"none", "up", "down", "both", "low", "high", NULL}; static const int opts_type[] = { GPIO_PIN_INTR_DISABLE, GPIO_PIN_INTR_POSEDGE, GPIO_PIN_INTR_NEGEDGE, GPIO_PIN_INTR_ANYEDGE, GPIO_PIN_INTR_LOLEVEL, GPIO_PIN_INTR_HILEVEL }; luaL_argcheck(L, platform_gpio_exists(pin) && pin>0, 1, "Invalid interrupt pin"); + + int old_pin_ref = gpio_cb_ref[pin]; int type = opts_type[luaL_checkoption(L, 2, "none", opts)]; - if (type != GPIO_PIN_INTR_DISABLE) { - int cbtype = lua_type(L, 3); - luaL_argcheck(L, cbtype == LUA_TFUNCTION || cbtype == LUA_TLIGHTFUNCTION, 3, - "invalid callback type"); - lua_pushvalue(L, 3); // copy argument (func) to the top of stack - gpio_cb_ref[pin] = luaL_ref(L, LUA_REGISTRYINDEX); - } else { + if (type == GPIO_PIN_INTR_DISABLE) { + // "none" clears the callback gpio_cb_ref[pin] = LUA_NOREF; + + } else if (lua_gettop(L)==2 && old_pin_ref != LUA_NOREF) { + // keep the old one if no callback + old_pin_ref = LUA_NOREF; + + } else if (lua_type(L, 3) == LUA_TFUNCTION || lua_type(L, 3) == LUA_TLIGHTFUNCTION) { + // set up the new callback if present + lua_pushvalue(L, 3); + gpio_cb_ref[pin] = luaL_ref(L, LUA_REGISTRYINDEX); + + } else { + // invalid combination, so clear down any old callback and throw an error + if(old_pin_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, old_pin_ref); + luaL_argcheck(L, 0, 3, "invalid callback type"); } + // unreference any overwritten callback if(old_pin_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, old_pin_ref); NODE_DBG("Pin data: %d %d %08x, %d %d %d, %08x\n", diff --git a/docs/en/modules/gpio.md b/docs/en/modules/gpio.md index d22af361..d2bae12b 100644 --- a/docs/en/modules/gpio.md +++ b/docs/en/modules/gpio.md @@ -103,14 +103,16 @@ Establish or clear a callback function to run on interrupt for a pin. This function is not available if GPIO_INTERRUPT_ENABLE was undefined at compile time. #### Syntax -`gpio.trig(pin, [type [, function(level)]})` +`gpio.trig(pin, [type [, callback_function]])` #### Parameters -- `pin` **1~12**, IO index, pin D0 does not support interrupt. -- `type` "up", "down", "both", "low", "high", which represent rising edge, falling edge, both edge, -low level, high level trig mode correspondingly. If the type is "none" or omitted then the -callback function is removed and the interrupt disabled. -- `function(level)` callback function when triggered. The gpio level is the param. Use previous callback function if undefined here. +- `pin` **1-12**, pin to trigger on, IO index. Note that pin 0 does not support interrupts. +- `type` "up", "down", "both", "low", "high", which represent *rising edge*, *falling edge*, *both +edges*, *low level*, and *high level* trigger modes respectivey. If the type is "none" or omitted +then the callback function is removed and the interrupt is disabled. +- `callback_function(level)` callback function when trigger occurs. The level of the specified pin +at the interrupt passed as the parameter to the callback. The previous callback function will be +used if the function is omitted. #### Returns `nil` @@ -118,23 +120,20 @@ callback function is removed and the interrupt disabled. #### Example ```lua --- use pin 1 as the input pulse width counter -pin = 1 -pulse1 = 0 -du = 0 -gpio.mode(pin,gpio.INT) -function pin1cb(level) - du = tmr.now() - pulse1 - print(du) - pulse1 = tmr.now() - if level == gpio.HIGH then gpio.trig(pin, "down") else gpio.trig(pin, "up") end +do + -- use pin 1 as the input pulse width counter + local pin, pulse1, du, now, trig = 1, 0, 0, tmr.now, gpio.trig + gpio.mode(pin,gpio.INT) + local function pin1cb(level) + local pulse2 = now() + print( level, pulse2 - pulse1 ) + pulse1 = pulse2 + trig(pin, level == gpio.HIGH and "down" or "up") + end + trig(pin, "down", pin1cb) end -gpio.trig(pin, "down", pin1cb) +``` -``` -```Lua -gpio.trig(4, 'none') -- remove any existing trigger -``` #### See also [`gpio.mode()`](#gpiomode)