123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- // Module for interfacing with GPIO
- #include "module.h"
- #include "lauxlib.h"
- #include "platform.h"
- #include "rom.h"
- #include "c_types.h"
- #include "c_string.h"
- #define PULLUP PLATFORM_GPIO_PULLUP
- #define FLOAT PLATFORM_GPIO_FLOAT
- #define OUTPUT PLATFORM_GPIO_OUTPUT
- #define INPUT PLATFORM_GPIO_INPUT
- #define INTERRUPT PLATFORM_GPIO_INT
- #define HIGH PLATFORM_GPIO_HIGH
- #define LOW PLATFORM_GPIO_LOW
- #ifdef GPIO_INTERRUPT_ENABLE
- static int gpio_cb_ref[GPIO_PIN_NUM];
- static lua_State* gL = NULL;
- void lua_gpio_unref(unsigned pin){
- if(gpio_cb_ref[pin] != LUA_NOREF){
- if(gL!=NULL)
- luaL_unref(gL, LUA_REGISTRYINDEX, gpio_cb_ref[pin]);
- }
- gpio_cb_ref[pin] = LUA_NOREF;
- }
- void gpio_intr_callback( unsigned pin, unsigned level )
- {
- NODE_DBG("pin:%d, level:%d \n", pin, level);
- if(gpio_cb_ref[pin] == LUA_NOREF)
- return;
- if(!gL)
- return;
- lua_rawgeti(gL, LUA_REGISTRYINDEX, gpio_cb_ref[pin]);
- lua_pushinteger(gL, level);
- lua_call(gL, 1, 0);
- }
- // Lua: trig( pin, type, function )
- static int lgpio_trig( lua_State* L )
- {
- unsigned type;
- unsigned pin;
- size_t sl;
-
- pin = luaL_checkinteger( L, 1 );
- MOD_CHECK_ID( gpio, pin );
- if(pin==0)
- return luaL_error( L, "no interrupt for D0" );
- const char *str = luaL_checklstring( L, 2, &sl );
- if (str == NULL)
- return luaL_error( L, "wrong arg type" );
- if(sl == 2 && c_strcmp(str, "up") == 0){
- type = GPIO_PIN_INTR_POSEDGE;
- }else if(sl == 4 && c_strcmp(str, "down") == 0){
- type = GPIO_PIN_INTR_NEGEDGE;
- }else if(sl == 4 && c_strcmp(str, "both") == 0){
- type = GPIO_PIN_INTR_ANYEDGE;
- }else if(sl == 3 && c_strcmp(str, "low") == 0){
- type = GPIO_PIN_INTR_LOLEVEL;
- }else if(sl == 4 && c_strcmp(str, "high") == 0){
- type = GPIO_PIN_INTR_HILEVEL;
- }else{
- type = GPIO_PIN_INTR_DISABLE;
- }
- // luaL_checkanyfunction(L, 3);
- if (lua_type(L, 3) == LUA_TFUNCTION || lua_type(L, 3) == LUA_TLIGHTFUNCTION){
- lua_pushvalue(L, 3); // copy argument (func) to the top of stack
- if(gpio_cb_ref[pin] != LUA_NOREF)
- luaL_unref(L, LUA_REGISTRYINDEX, gpio_cb_ref[pin]);
- gpio_cb_ref[pin] = luaL_ref(L, LUA_REGISTRYINDEX);
- }
- platform_gpio_intr_init(pin, type);
- return 0;
- }
- #endif
- // Lua: mode( pin, mode, pullup )
- static int lgpio_mode( lua_State* L )
- {
- unsigned mode, pullup = FLOAT;
- unsigned pin;
- pin = luaL_checkinteger( L, 1 );
- MOD_CHECK_ID( gpio, pin );
- mode = luaL_checkinteger( L, 2 );
- if ( mode!=OUTPUT && mode!=INPUT && mode!=INTERRUPT)
- return luaL_error( L, "wrong arg type" );
- if(pin==0 && mode==INTERRUPT)
- return luaL_error( L, "no interrupt for D0" );
- if(lua_isnumber(L, 3))
- pullup = lua_tointeger( L, 3 );
- if(pullup!=FLOAT)
- pullup = PULLUP;
- #ifdef GPIO_INTERRUPT_ENABLE
- gL = L; // save to local gL, for callback function
- if (mode!=INTERRUPT){ // disable interrupt
- if(gpio_cb_ref[pin] != LUA_NOREF){
- luaL_unref(L, LUA_REGISTRYINDEX, gpio_cb_ref[pin]);
- }
- gpio_cb_ref[pin] = LUA_NOREF;
- }
- #endif
- int r = platform_gpio_mode( pin, mode, pullup );
- if( r<0 )
- return luaL_error( L, "wrong pin num." );
- return 0;
- }
- // Lua: read( pin )
- static int lgpio_read( lua_State* L )
- {
- unsigned pin;
-
- pin = luaL_checkinteger( L, 1 );
- MOD_CHECK_ID( gpio, pin );
- unsigned level = platform_gpio_read( pin );
- lua_pushinteger( L, level );
- return 1;
- }
- // Lua: write( pin, level )
- static int lgpio_write( lua_State* L )
- {
- unsigned level;
- unsigned pin;
-
- pin = luaL_checkinteger( L, 1 );
- MOD_CHECK_ID( gpio, pin );
- level = luaL_checkinteger( L, 2 );
- if ( level!=HIGH && level!=LOW )
- return luaL_error( L, "wrong arg type" );
- platform_gpio_write(pin, level);
- return 0;
- }
- #define DELAY_TABLE_MAX_LEN 256
- #define noInterrupts ets_intr_lock
- #define interrupts ets_intr_unlock
- #define delayMicroseconds os_delay_us
- #define DIRECT_WRITE(pin, level) (GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), level))
- // Lua: serout( pin, firstLevel, delay_table, [repeatNum] )
- // -- serout( pin, firstLevel, delay_table, [repeatNum] )
- // gpio.mode(1,gpio.OUTPUT,gpio.PULLUP)
- // gpio.serout(1,1,{30,30,60,60,30,30}) -- serial one byte, b10110010
- // gpio.serout(1,1,{30,70},8) -- serial 30% pwm 10k, lasts 8 cycles
- // gpio.serout(1,1,{3,7},8) -- serial 30% pwm 100k, lasts 8 cycles
- // gpio.serout(1,1,{0,0},8) -- serial 50% pwm as fast as possible, lasts 8 cycles
- // gpio.mode(1,gpio.OUTPUT,gpio.PULLUP)
- // gpio.serout(1,0,{20,10,10,20,10,10,10,100}) -- sim uart one byte 0x5A at about 100kbps
- // gpio.serout(1,1,{8,18},8) -- serial 30% pwm 38k, lasts 8 cycles
- static int lgpio_serout( lua_State* L )
- {
- unsigned level;
- unsigned pin;
- unsigned table_len = 0;
- unsigned repeat = 0;
- int delay_table[DELAY_TABLE_MAX_LEN];
-
- pin = luaL_checkinteger( L, 1 );
- MOD_CHECK_ID( gpio, pin );
- level = luaL_checkinteger( L, 2 );
- if ( level!=HIGH && level!=LOW )
- return luaL_error( L, "wrong arg type" );
- if( lua_istable( L, 3 ) )
- {
- table_len = lua_objlen( L, 3 );
- if (table_len <= 0 || table_len>DELAY_TABLE_MAX_LEN)
- return luaL_error( L, "wrong arg range" );
- int i;
- for( i = 0; i < table_len; i ++ )
- {
- lua_rawgeti( L, 3, i + 1 );
- delay_table[i] = ( int )luaL_checkinteger( L, -1 );
- lua_pop( L, 1 );
- if( delay_table[i] < 0 || delay_table[i] > 1000000 ) // can not delay more than 1000000 us
- return luaL_error( L, "delay must < 1000000 us" );
- }
- } else {
- return luaL_error( L, "wrong arg range" );
- }
- if(lua_isnumber(L, 4))
- repeat = lua_tointeger( L, 4 );
- if( repeat < 0 || repeat > DELAY_TABLE_MAX_LEN )
- return luaL_error( L, "delay must < 256" );
- if(repeat==0)
- repeat = 1;
- int j;
- bool skip_loop = true;
- do
- {
- if(skip_loop){ // skip the first loop.
- skip_loop = false;
- continue;
- }
- for(j=0;j<table_len;j++){
- noInterrupts();
- // platform_gpio_write(pin, level);
- DIRECT_WRITE(pin, level);
- interrupts();
- delayMicroseconds(delay_table[j]);
- level=!level;
- }
- repeat--;
- } while (repeat>0);
- return 0;
- }
- #undef DELAY_TABLE_MAX_LEN
- // Module function map
- static const LUA_REG_TYPE gpio_map[] = {
- { LSTRKEY( "mode" ), LFUNCVAL( lgpio_mode ) },
- { LSTRKEY( "read" ), LFUNCVAL( lgpio_read ) },
- { LSTRKEY( "write" ), LFUNCVAL( lgpio_write ) },
- { LSTRKEY( "serout" ), LFUNCVAL( lgpio_serout ) },
- #ifdef GPIO_INTERRUPT_ENABLE
- { 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 ) },
- { LNILKEY, LNILVAL }
- };
- int luaopen_gpio( lua_State *L ) {
- #ifdef GPIO_INTERRUPT_ENABLE
- int i;
- for(i=0;i<GPIO_PIN_NUM;i++){
- gpio_cb_ref[i] = LUA_NOREF;
- }
- platform_gpio_init(gpio_intr_callback);
- #endif
- return 0;
- }
- NODEMCU_MODULE(GPIO, "gpio", gpio_map, luaopen_gpio);
|