gpio.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. // Module for interfacing with GPIO
  2. //#define NODE_DEBUG
  3. #include "module.h"
  4. #include "lauxlib.h"
  5. #include "lmem.h"
  6. #include "platform.h"
  7. #include "task/task.h"
  8. #include "user_interface.h"
  9. #include <stdint.h>
  10. #include <string.h>
  11. #include "gpio.h"
  12. #include "hw_timer.h"
  13. #define PULLUP PLATFORM_GPIO_PULLUP
  14. #define FLOAT PLATFORM_GPIO_FLOAT
  15. #define OUTPUT PLATFORM_GPIO_OUTPUT
  16. #define OPENDRAIN PLATFORM_GPIO_OPENDRAIN
  17. #define INPUT PLATFORM_GPIO_INPUT
  18. #define INTERRUPT PLATFORM_GPIO_INT
  19. #define HIGH PLATFORM_GPIO_HIGH
  20. #define LOW PLATFORM_GPIO_LOW
  21. #ifdef GPIO_INTERRUPT_ENABLE
  22. // We also know that the non-level interrupt types are < LOLEVEL, and that
  23. // HILEVEL is > LOLEVEL. Since this is burned into the hardware it is not
  24. // going to change.
  25. #define INTERRUPT_TYPE_IS_LEVEL(x) ((x) >= GPIO_PIN_INTR_LOLEVEL)
  26. static int gpio_cb_ref[GPIO_PIN_NUM];
  27. // This task is scheduled by the ISR and is used
  28. // to initiate the Lua-land gpio.trig() callback function
  29. // It also re-enables the pin interrupt, so that we get another callback queued
  30. static void gpio_intr_callback_task (task_param_t param, uint8 priority)
  31. {
  32. uint32_t then = (param >> 8) & 0xffffff;
  33. uint32_t pin = (param >> 1) & 127;
  34. uint32_t level = param & 1;
  35. UNUSED(priority);
  36. uint32_t now = system_get_time();
  37. // Now must be >= then . Add the missing bits
  38. if (then > (now & 0xffffff)) {
  39. // Now must have rolled over since the interrupt -- back it down
  40. now -= 0x1000000;
  41. }
  42. then = (then + (now & 0x7f000000)) & 0x7fffffff;
  43. NODE_DBG("pin:%d, level:%d \n", pin, level);
  44. if(gpio_cb_ref[pin] != LUA_NOREF) {
  45. // GPIO callbacks are run in L0 and include the level as a parameter
  46. lua_State *L = lua_getstate();
  47. NODE_DBG("Calling: %08x\n", gpio_cb_ref[pin]);
  48. bool needs_callback = 1;
  49. while (needs_callback) {
  50. // Note that the interrupt level only modifies 'seen' and
  51. // the base level only modifies 'reported'.
  52. // Do the actual callback
  53. lua_rawgeti(L, LUA_REGISTRYINDEX, gpio_cb_ref[pin]);
  54. lua_pushinteger(L, level);
  55. lua_pushinteger(L, then);
  56. uint16_t seen = pin_counter[pin].seen;
  57. lua_pushinteger(L, 0x7fff & (seen - pin_counter[pin].reported));
  58. pin_counter[pin].reported = seen & 0x7fff; // This will cause the next interrupt to trigger a callback
  59. uint16_t diff = (seen ^ pin_counter[pin].seen);
  60. // Needs another callback if seen changed but not if the top bit is set
  61. needs_callback = diff <= 0x7fff && diff > 0;
  62. if (needs_callback) {
  63. // Fake this for next time (this only happens if another interrupt happens since
  64. // we loaded the 'seen' variable.
  65. then = system_get_time() & 0x7fffffff;
  66. }
  67. lua_call(L, 3, 0);
  68. }
  69. if (INTERRUPT_TYPE_IS_LEVEL(pin_int_type[pin])) {
  70. // Level triggered -- re-enable the callback
  71. platform_gpio_intr_init(pin, pin_int_type[pin]);
  72. }
  73. }
  74. }
  75. // Lua: trig( pin, type, function )
  76. static int lgpio_trig( lua_State* L )
  77. {
  78. unsigned pin = luaL_checkinteger( L, 1 );
  79. static const char * const opts[] = {"none", "up", "down", "both", "low", "high", NULL};
  80. static const int opts_type[] = {
  81. GPIO_PIN_INTR_DISABLE, GPIO_PIN_INTR_POSEDGE, GPIO_PIN_INTR_NEGEDGE,
  82. GPIO_PIN_INTR_ANYEDGE, GPIO_PIN_INTR_LOLEVEL, GPIO_PIN_INTR_HILEVEL
  83. };
  84. luaL_argcheck(L, platform_gpio_exists(pin) && pin>0, 1, "Invalid interrupt pin");
  85. int old_pin_ref = gpio_cb_ref[pin];
  86. int type = opts_type[luaL_checkoption(L, 2, "none", opts)];
  87. if (type == GPIO_PIN_INTR_DISABLE) {
  88. // "none" clears the callback
  89. gpio_cb_ref[pin] = LUA_NOREF;
  90. } else if (lua_gettop(L)==2 && old_pin_ref != LUA_NOREF) {
  91. // keep the old one if no callback
  92. old_pin_ref = LUA_NOREF;
  93. } else if (lua_type(L, 3) == LUA_TFUNCTION || lua_type(L, 3) == LUA_TLIGHTFUNCTION) {
  94. // set up the new callback if present
  95. lua_pushvalue(L, 3);
  96. gpio_cb_ref[pin] = luaL_ref(L, LUA_REGISTRYINDEX);
  97. } else {
  98. // invalid combination, so clear down any old callback and throw an error
  99. if(old_pin_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, old_pin_ref);
  100. luaL_argcheck(L, 0, 3, "invalid callback type");
  101. }
  102. // unreference any overwritten callback
  103. if(old_pin_ref != LUA_NOREF) luaL_unref(L, LUA_REGISTRYINDEX, old_pin_ref);
  104. uint16_t seen;
  105. // Make sure that we clear out any queued interrupts
  106. do {
  107. seen = pin_counter[pin].seen;
  108. pin_counter[pin].reported = seen & 0x7fff;
  109. } while (seen != pin_counter[pin].seen);
  110. NODE_DBG("Pin data: %d %d %08x, %d %d %d, %08x\n",
  111. pin, type, pin_mux[pin], pin_num[pin], pin_func[pin], pin_int_type[pin], gpio_cb_ref[pin]);
  112. platform_gpio_intr_init(pin, type);
  113. return 0;
  114. }
  115. #endif
  116. // Lua: mode( pin, mode, pullup )
  117. static int lgpio_mode( lua_State* L )
  118. {
  119. unsigned pin = luaL_checkinteger( L, 1 );
  120. unsigned mode = luaL_checkinteger( L, 2 );
  121. unsigned pullup = luaL_optinteger( L, 3, FLOAT );
  122. luaL_argcheck(L, platform_gpio_exists(pin) && (mode!=INTERRUPT || pin>0), 1, "Invalid pin");
  123. luaL_argcheck(L, mode==OUTPUT || mode==OPENDRAIN || mode==INPUT
  124. #ifdef GPIO_INTERRUPT_ENABLE
  125. || mode==INTERRUPT
  126. #endif
  127. , 2, "wrong arg type" );
  128. if(pullup!=FLOAT) pullup = PULLUP;
  129. NODE_DBG("pin,mode,pullup= %d %d %d\n",pin,mode,pullup);
  130. NODE_DBG("Pin data at mode: %d %08x, %d %d %d, %08x\n",
  131. pin, pin_mux[pin], pin_num[pin], pin_func[pin],
  132. #ifdef GPIO_INTERRUPT_ENABLE
  133. pin_int_type[pin], gpio_cb_ref[pin]
  134. #else
  135. 0, 0
  136. #endif
  137. );
  138. #ifdef GPIO_INTERRUPT_ENABLE
  139. if (mode != INTERRUPT){ // disable interrupt
  140. if(gpio_cb_ref[pin] != LUA_NOREF){
  141. luaL_unref(L, LUA_REGISTRYINDEX, gpio_cb_ref[pin]);
  142. gpio_cb_ref[pin] = LUA_NOREF;
  143. }
  144. }
  145. #endif
  146. if( platform_gpio_mode( pin, mode, pullup ) < 0 )
  147. return luaL_error( L, "wrong pin num." );
  148. return 0;
  149. }
  150. // Lua: read( pin )
  151. static int lgpio_read( lua_State* L )
  152. {
  153. unsigned pin = luaL_checkinteger( L, 1 );
  154. MOD_CHECK_ID( gpio, pin );
  155. lua_pushinteger( L, platform_gpio_read( pin ) );
  156. return 1;
  157. }
  158. // Lua: write( pin, level )
  159. static int lgpio_write( lua_State* L )
  160. {
  161. unsigned pin = luaL_checkinteger( L, 1 );
  162. unsigned level = luaL_checkinteger( L, 2 );
  163. MOD_CHECK_ID( gpio, pin );
  164. luaL_argcheck(L, level==HIGH || level==LOW, 2, "wrong level type" );
  165. platform_gpio_write(pin, level);
  166. return 0;
  167. }
  168. #define DELAY_TABLE_MAX_LEN 256
  169. #define delayMicroseconds os_delay_us
  170. // Lua: serout( pin, firstLevel, delay_table[, repeat_num[, callback]])
  171. // gpio.mode(1,gpio.OUTPUT,gpio.PULLUP)
  172. // gpio.serout(1,1,{30,30,60,60,30,30}) -- serial one byte, b10110010
  173. // gpio.serout(1,1,{30,70},8) -- serial 30% pwm 10k, lasts 8 cycles
  174. // gpio.serout(1,1,{3,7},8) -- serial 30% pwm 100k, lasts 8 cycles
  175. // gpio.serout(1,1,{0,0},8) -- serial 50% pwm as fast as possible, lasts 8 cycles
  176. // gpio.mode(1,gpio.OUTPUT,gpio.PULLUP)
  177. // gpio.serout(1,0,{20,10,10,20,10,10,10,100}) -- sim uart one byte 0x5A at about 100kbps
  178. // gpio.serout(1,1,{8,18},8) -- serial 30% pwm 38k, lasts 8 cycles
  179. typedef struct
  180. {
  181. unsigned pin;
  182. unsigned level;
  183. uint32 index;
  184. uint32 repeats;
  185. uint32 *delay_table;
  186. uint32 tablelen;
  187. task_handle_t done_taskid;
  188. int lua_done_ref; // callback when transmission is done
  189. } serout_t;
  190. static serout_t serout;
  191. static const os_param_t TIMER_OWNER = 0x6770696f; // "gpio"
  192. static void seroutasync_done (task_param_t arg)
  193. {
  194. lua_State *L = lua_getstate();
  195. if (serout.delay_table) {
  196. luaM_freearray(L, serout.delay_table, serout.tablelen, uint32);
  197. serout.delay_table = NULL;
  198. }
  199. if (serout.lua_done_ref != LUA_NOREF) {
  200. lua_rawgeti (L, LUA_REGISTRYINDEX, serout.lua_done_ref);
  201. luaL_unref (L, LUA_REGISTRYINDEX, serout.lua_done_ref);
  202. serout.lua_done_ref = LUA_NOREF;
  203. if (lua_pcall(L, 0, 0, 0)) {
  204. // Uncaught Error. Print instead of sudden reset
  205. luaL_error(L, "error: %s", lua_tostring(L, -1));
  206. }
  207. }
  208. }
  209. static void ICACHE_RAM_ATTR seroutasync_cb(os_param_t p) {
  210. (void) p;
  211. if (serout.index < serout.tablelen) {
  212. GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[serout.pin]), serout.level);
  213. serout.level = serout.level==LOW ? HIGH : LOW;
  214. platform_hw_timer_arm_us(TIMER_OWNER, serout.delay_table[serout.index]);
  215. serout.index++;
  216. if (serout.repeats && serout.index>=serout.tablelen) {serout.index=0; serout.repeats--;}
  217. } else {
  218. platform_hw_timer_close(TIMER_OWNER);
  219. task_post_low (serout.done_taskid, (task_param_t)0);
  220. }
  221. }
  222. static int lgpio_serout( lua_State* L )
  223. {
  224. serout.pin = luaL_checkinteger( L, 1 );
  225. serout.level = luaL_checkinteger( L, 2 );
  226. serout.repeats = luaL_optint( L, 4, 1 )-1;
  227. luaL_unref (L, LUA_REGISTRYINDEX, serout.lua_done_ref);
  228. uint8_t is_async = FALSE;
  229. if (!lua_isnoneornil(L, 5)) {
  230. if (lua_isnumber(L, 5)) {
  231. serout.lua_done_ref = LUA_NOREF;
  232. } else {
  233. lua_pushvalue(L, 5);
  234. serout.lua_done_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  235. }
  236. is_async = TRUE;
  237. } else {
  238. serout.lua_done_ref = LUA_NOREF;
  239. }
  240. if (serout.delay_table) {
  241. luaM_freearray(L, serout.delay_table, serout.tablelen, uint32);
  242. serout.delay_table = NULL;
  243. }
  244. luaL_argcheck(L, platform_gpio_exists(serout.pin), 1, "Invalid pin");
  245. luaL_argcheck(L, serout.level==HIGH || serout.level==LOW, 2, "Wrong level type" );
  246. luaL_argcheck(L, lua_istable( L, 3 ) &&
  247. ((serout.tablelen = lua_objlen( L, 3 )) < DELAY_TABLE_MAX_LEN), 3, "Invalid delay_times" );
  248. serout.delay_table = luaM_newvector(L, serout.tablelen, uint32);
  249. for(unsigned i = 0; i < serout.tablelen; i++ ) {
  250. lua_rawgeti( L, 3, i + 1 );
  251. unsigned delay = (unsigned) luaL_checkinteger( L, -1 );
  252. serout.delay_table[i] = delay;
  253. lua_pop( L, 1 );
  254. }
  255. if (is_async) { // async version for duration above 15 mSec
  256. if (!platform_hw_timer_init(TIMER_OWNER, FRC1_SOURCE, TRUE)) {
  257. // Failed to init the timer
  258. luaL_error(L, "Unable to initialize timer");
  259. }
  260. platform_hw_timer_set_func(TIMER_OWNER, seroutasync_cb, 0);
  261. serout.index = 0;
  262. seroutasync_cb(0);
  263. } else { // sync version for sub-50 µs resolution & total duration < 15 mSec
  264. do {
  265. for( serout.index = 0;serout.index < serout.tablelen; serout.index++ ){
  266. NODE_DBG("%d\t%d\t%d\t%d\t%d\t%d\t%d\n", serout.repeats, serout.index, serout.level, serout.pin, serout.tablelen, serout.delay_table[serout.index], system_get_time()); // timings is delayed for short timings when debug output is enabled
  267. GPIO_OUTPUT_SET(GPIO_ID_PIN(pin_num[serout.pin]), serout.level);
  268. serout.level = serout.level==LOW ? HIGH : LOW;
  269. delayMicroseconds(serout.delay_table[serout.index]);
  270. }
  271. } while (serout.repeats--);
  272. luaM_freearray(L, serout.delay_table, serout.tablelen, uint32);
  273. serout.delay_table = NULL;
  274. }
  275. return 0;
  276. }
  277. #undef DELAY_TABLE_MAX_LEN
  278. #ifdef LUA_USE_MODULES_GPIO_PULSE
  279. LROT_EXTERN(gpio_pulse);
  280. extern int gpio_pulse_init(lua_State *);
  281. #endif
  282. // Module function map
  283. LROT_BEGIN(gpio)
  284. LROT_FUNCENTRY( mode, lgpio_mode )
  285. LROT_FUNCENTRY( read, lgpio_read )
  286. LROT_FUNCENTRY( write, lgpio_write )
  287. LROT_FUNCENTRY( serout, lgpio_serout )
  288. #ifdef LUA_USE_MODULES_GPIO_PULSE
  289. LROT_TABENTRY( pulse, gpio_pulse )
  290. #endif
  291. #ifdef GPIO_INTERRUPT_ENABLE
  292. LROT_FUNCENTRY( trig, lgpio_trig )
  293. LROT_NUMENTRY( INT, INTERRUPT )
  294. #endif
  295. LROT_NUMENTRY( OUTPUT, OUTPUT )
  296. LROT_NUMENTRY( OPENDRAIN, OPENDRAIN )
  297. LROT_NUMENTRY( INPUT, INPUT )
  298. LROT_NUMENTRY( HIGH, HIGH )
  299. LROT_NUMENTRY( LOW, LOW )
  300. LROT_NUMENTRY( FLOAT, FLOAT )
  301. LROT_NUMENTRY( PULLUP, PULLUP )
  302. LROT_END( gpio, NULL, 0 )
  303. int luaopen_gpio( lua_State *L ) {
  304. #ifdef LUA_USE_MODULES_GPIO_PULSE
  305. gpio_pulse_init(L);
  306. #endif
  307. #ifdef GPIO_INTERRUPT_ENABLE
  308. int i;
  309. for(i=0;i<GPIO_PIN_NUM;i++){
  310. gpio_cb_ref[i] = LUA_NOREF;
  311. }
  312. platform_gpio_init(task_get_id(gpio_intr_callback_task));
  313. #endif
  314. serout.done_taskid = task_get_id((task_callback_t) seroutasync_done);
  315. serout.lua_done_ref = LUA_NOREF;
  316. return 0;
  317. }
  318. NODEMCU_MODULE(GPIO, "gpio", gpio, luaopen_gpio);