gpio.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Module for interfacing with GPIO
  2. #include "module.h"
  3. #include "lauxlib.h"
  4. #include "lmem.h"
  5. #include "platform.h"
  6. #include "user_interface.h"
  7. #include "c_types.h"
  8. #include "c_string.h"
  9. #include "gpio.h"
  10. #define PULLUP PLATFORM_GPIO_PULLUP
  11. #define FLOAT PLATFORM_GPIO_FLOAT
  12. #define OUTPUT PLATFORM_GPIO_OUTPUT
  13. #define OPENDRAIN PLATFORM_GPIO_OPENDRAIN
  14. #define INPUT PLATFORM_GPIO_INPUT
  15. #define INTERRUPT PLATFORM_GPIO_INT
  16. #define HIGH PLATFORM_GPIO_HIGH
  17. #define LOW PLATFORM_GPIO_LOW
  18. #ifdef GPIO_INTERRUPT_ENABLE
  19. // We also know that the non-level interrupt types are < LOLEVEL, and that
  20. // HILEVEL is > LOLEVEL. Since this is burned into the hardware it is not
  21. // going to change.
  22. #define INTERRUPT_TYPE_IS_LEVEL(x) ((x) >= GPIO_PIN_INTR_LOLEVEL)
  23. static int gpio_cb_ref[GPIO_PIN_NUM];
  24. // This task is scheduled by the ISR and is used
  25. // to initiate the Lua-land gpio.trig() callback function
  26. // It also re-enables the pin interrupt, so that we get another callback queued
  27. static void gpio_intr_callback_task (task_param_t param, uint8 priority)
  28. {
  29. unsigned pin = param >> 1;
  30. unsigned level = param & 1;
  31. UNUSED(priority);
  32. NODE_DBG("pin:%d, level:%d \n", pin, level);
  33. if(gpio_cb_ref[pin] != LUA_NOREF) {
  34. // GPIO callbacks are run in L0 and inlcude the level as a parameter
  35. lua_State *L = lua_getstate();
  36. NODE_DBG("Calling: %08x\n", gpio_cb_ref[pin]);
  37. //
  38. if (!INTERRUPT_TYPE_IS_LEVEL(pin_int_type[pin])) {
  39. // Edge triggered -- re-enable the interrupt
  40. platform_gpio_intr_init(pin, pin_int_type[pin]);
  41. }
  42. // Do the actual callback
  43. lua_rawgeti(L, LUA_REGISTRYINDEX, gpio_cb_ref[pin]);
  44. lua_pushinteger(L, level);
  45. lua_call(L, 1, 0);
  46. if (INTERRUPT_TYPE_IS_LEVEL(pin_int_type[pin])) {
  47. // Level triggered -- re-enable the callback
  48. platform_gpio_intr_init(pin, pin_int_type[pin]);
  49. }
  50. }
  51. }
  52. // Lua: trig( pin, type, function )
  53. static int lgpio_trig( lua_State* L )
  54. {
  55. unsigned pin = luaL_checkinteger( L, 1 );
  56. static const char * const opts[] = {"none", "up", "down", "both", "low", "high", NULL};
  57. static const int opts_type[] = {
  58. GPIO_PIN_INTR_DISABLE, GPIO_PIN_INTR_POSEDGE, GPIO_PIN_INTR_NEGEDGE,
  59. GPIO_PIN_INTR_ANYEDGE, GPIO_PIN_INTR_LOLEVEL, GPIO_PIN_INTR_HILEVEL
  60. };
  61. luaL_argcheck(L, platform_gpio_exists(pin) && pin>0, 1, "Invalid interrupt pin");
  62. int old_pin_ref = gpio_cb_ref[pin];
  63. int type = opts_type[luaL_checkoption(L, 2, "none", opts)];
  64. if (type == GPIO_PIN_INTR_DISABLE) {
  65. // "none" clears the callback
  66. gpio_cb_ref[pin] = LUA_NOREF;
  67. } else if (lua_gettop(L)==2 && old_pin_ref != LUA_NOREF) {
  68. // keep the old one if no callback
  69. old_pin_ref = LUA_NOREF;
  70. } else if (lua_type(L, 3) == LUA_TFUNCTION || lua_type(L, 3) == LUA_TLIGHTFUNCTION) {
  71. // set up the new callback if present
  72. lua_pushvalue(L, 3);
  73. gpio_cb_ref[pin] = luaL_ref(L, LUA_REGISTRYINDEX);
  74. } else {
  75. // invalid combination, so clear down any old callback and throw an error
  76. if(old_pin_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, old_pin_ref);
  77. luaL_argcheck(L, 0, 3, "invalid callback type");
  78. }
  79. // unreference any overwritten callback
  80. if(old_pin_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, old_pin_ref);
  81. NODE_DBG("Pin data: %d %d %08x, %d %d %d, %08x\n",
  82. pin, type, pin_mux[pin], pin_num[pin], pin_func[pin], pin_int_type[pin], gpio_cb_ref[pin]);
  83. platform_gpio_intr_init(pin, type);
  84. return 0;
  85. }
  86. #endif
  87. // Lua: mode( pin, mode, pullup )
  88. static int lgpio_mode( lua_State* L )
  89. {
  90. unsigned pin = luaL_checkinteger( L, 1 );
  91. unsigned mode = luaL_checkinteger( L, 2 );
  92. unsigned pullup = luaL_optinteger( L, 3, FLOAT );
  93. luaL_argcheck(L, platform_gpio_exists(pin) && (mode!=INTERRUPT || pin>0), 1, "Invalid pin");
  94. luaL_argcheck(L, mode==OUTPUT || mode==OPENDRAIN || mode==INPUT
  95. #ifdef GPIO_INTERRUPT_ENABLE
  96. || mode==INTERRUPT
  97. #endif
  98. , 2, "wrong arg type" );
  99. if(pullup!=FLOAT) pullup = PULLUP;
  100. NODE_DBG("pin,mode,pullup= %d %d %d\n",pin,mode,pullup);
  101. NODE_DBG("Pin data at mode: %d %08x, %d %d %d, %08x\n",
  102. pin, pin_mux[pin], pin_num[pin], pin_func[pin], pin_int_type[pin], gpio_cb_ref[pin]);
  103. #ifdef GPIO_INTERRUPT_ENABLE
  104. if (mode != INTERRUPT){ // disable interrupt
  105. if(gpio_cb_ref[pin] != LUA_NOREF){
  106. luaL_unref(L, LUA_REGISTRYINDEX, gpio_cb_ref[pin]);
  107. gpio_cb_ref[pin] = LUA_NOREF;
  108. }
  109. }
  110. #endif
  111. if( platform_gpio_mode( pin, mode, pullup ) < 0 )
  112. return luaL_error( L, "wrong pin num." );
  113. return 0;
  114. }
  115. // Lua: read( pin )
  116. static int lgpio_read( lua_State* L )
  117. {
  118. unsigned pin = luaL_checkinteger( L, 1 );
  119. MOD_CHECK_ID( gpio, pin );
  120. lua_pushinteger( L, platform_gpio_read( pin ) );
  121. return 1;
  122. }
  123. // Lua: write( pin, level )
  124. static int lgpio_write( lua_State* L )
  125. {
  126. unsigned pin = luaL_checkinteger( L, 1 );
  127. unsigned level = luaL_checkinteger( L, 2 );
  128. MOD_CHECK_ID( gpio, pin );
  129. luaL_argcheck(L, level==HIGH || level==LOW, 2, "wrong level type" );
  130. platform_gpio_write(pin, level);
  131. return 0;
  132. }
  133. #define DELAY_TABLE_MAX_LEN 256
  134. #define delayMicroseconds os_delay_us
  135. // Lua: serout( pin, firstLevel, delay_table, [repeatNum] )
  136. // -- serout( pin, firstLevel, delay_table, [repeatNum] )
  137. // gpio.mode(1,gpio.OUTPUT,gpio.PULLUP)
  138. // gpio.serout(1,1,{30,30,60,60,30,30}) -- serial one byte, b10110010
  139. // gpio.serout(1,1,{30,70},8) -- serial 30% pwm 10k, lasts 8 cycles
  140. // gpio.serout(1,1,{3,7},8) -- serial 30% pwm 100k, lasts 8 cycles
  141. // gpio.serout(1,1,{0,0},8) -- serial 50% pwm as fast as possible, lasts 8 cycles
  142. // gpio.mode(1,gpio.OUTPUT,gpio.PULLUP)
  143. // gpio.serout(1,0,{20,10,10,20,10,10,10,100}) -- sim uart one byte 0x5A at about 100kbps
  144. // gpio.serout(1,1,{8,18},8) -- serial 30% pwm 38k, lasts 8 cycles
  145. static int lgpio_serout( lua_State* L )
  146. {
  147. unsigned clocks_per_us = system_get_cpu_freq();
  148. unsigned pin = luaL_checkinteger( L, 1 );
  149. unsigned level = luaL_checkinteger( L, 2 );
  150. unsigned repeats = luaL_optint( L, 4, 1 );
  151. unsigned table_len, i, j;
  152. luaL_argcheck(L, platform_gpio_exists(pin), 1, "Invalid pin");
  153. luaL_argcheck(L, level==HIGH || level==LOW, 2, "Wrong arg type" );
  154. luaL_argcheck(L, lua_istable( L, 3 ) &&
  155. ((table_len = lua_objlen( L, 3 )<DELAY_TABLE_MAX_LEN)), 3, "Invalid table" );
  156. luaL_argcheck(L, repeats<256, 4, "repeats >= 256" );
  157. uint32 *delay_table = luaM_newvector(L, table_len*repeats, uint32);
  158. for( i = 1; i <= table_len; i++ ) {
  159. lua_rawgeti( L, 3, i + 1 );
  160. unsigned delay = (unsigned) luaL_checkinteger( L, -1 );
  161. if (delay > 1000000) return luaL_error( L, "delay %u must be < 1,000,000 us", i );
  162. delay_table[i-1] = delay;
  163. lua_pop( L, 1 );
  164. }
  165. for( i = 0; i <= repeats; i++ ) {
  166. if (!i) // skip the first loop (presumably this is some form of icache priming??).
  167. continue;
  168. for( j = 0;j < table_len; j++ ){
  169. /* Direct Write is a ROM function which already disables interrupts for the atomic bit */
  170. GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[pin]), level);
  171. delayMicroseconds(delay_table[j]);
  172. level = level==LOW ? HIGH : LOW;
  173. }
  174. }
  175. luaM_freearray(L, delay_table, table_len, uint32);
  176. return 0;
  177. }
  178. #undef DELAY_TABLE_MAX_LEN
  179. // Module function map
  180. static const LUA_REG_TYPE gpio_map[] = {
  181. { LSTRKEY( "mode" ), LFUNCVAL( lgpio_mode ) },
  182. { LSTRKEY( "read" ), LFUNCVAL( lgpio_read ) },
  183. { LSTRKEY( "write" ), LFUNCVAL( lgpio_write ) },
  184. { LSTRKEY( "serout" ), LFUNCVAL( lgpio_serout ) },
  185. #ifdef GPIO_INTERRUPT_ENABLE
  186. { LSTRKEY( "trig" ), LFUNCVAL( lgpio_trig ) },
  187. { LSTRKEY( "INT" ), LNUMVAL( INTERRUPT ) },
  188. #endif
  189. { LSTRKEY( "OUTPUT" ), LNUMVAL( OUTPUT ) },
  190. { LSTRKEY( "OPENDRAIN" ), LNUMVAL( OPENDRAIN ) },
  191. { LSTRKEY( "INPUT" ), LNUMVAL( INPUT ) },
  192. { LSTRKEY( "HIGH" ), LNUMVAL( HIGH ) },
  193. { LSTRKEY( "LOW" ), LNUMVAL( LOW ) },
  194. { LSTRKEY( "FLOAT" ), LNUMVAL( FLOAT ) },
  195. { LSTRKEY( "PULLUP" ), LNUMVAL( PULLUP ) },
  196. { LNILKEY, LNILVAL }
  197. };
  198. int luaopen_gpio( lua_State *L ) {
  199. #ifdef GPIO_INTERRUPT_ENABLE
  200. int i;
  201. for(i=0;i<GPIO_PIN_NUM;i++){
  202. gpio_cb_ref[i] = LUA_NOREF;
  203. }
  204. platform_gpio_init(task_get_id(gpio_intr_callback_task));
  205. #endif
  206. return 0;
  207. }
  208. NODEMCU_MODULE(GPIO, "gpio", gpio_map, luaopen_gpio);