luat_lib_io_queue.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. @module ioqueue
  3. @summary io序列操作
  4. @version 1.0
  5. @date 2022.03.13
  6. @demo io_queue
  7. @tag LUAT_USE_IO_QUEUE
  8. */
  9. #include "luat_base.h"
  10. #include "luat_multimedia.h"
  11. #include "luat_msgbus.h"
  12. #include "luat_zbuff.h"
  13. #include "luat_lib_io_queue.h"
  14. #define LUAT_LOG_TAG "io_queue"
  15. #include "luat_log.h"
  16. int l_io_queue_done_handler(lua_State *L, void* ptr)
  17. {
  18. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  19. lua_pop(L, 1);
  20. lua_getglobal(L, "sys_pub");
  21. lua_pushfstring(L, "IO_QUEUE_DONE_%d", msg->ptr);
  22. lua_call(L, 1, 0);
  23. return 1;
  24. }
  25. int l_io_queue_capture_handler(lua_State *L, void* ptr)
  26. {
  27. volatile uint64_t tick;
  28. uint32_t pin;
  29. uint32_t val;
  30. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  31. lua_getglobal(L, "sys_pub");
  32. pin = ((uint32_t)msg->ptr >> 8) & 0x000000ff;
  33. val = (uint32_t)msg->ptr & 0x00000001;
  34. tick = ((uint64_t)msg->arg1 << 32) | (uint32_t)msg->arg2;
  35. // LLOGD("%u, %x,%x, %llu",pin, msg->arg1, msg->arg2, tick);
  36. lua_pushfstring(L, "IO_QUEUE_EXTI_%d", pin);
  37. lua_pushinteger(L, val);
  38. lua_pushlstring(L, &tick, 8);
  39. lua_call(L, 3, 0);
  40. return 1;
  41. }
  42. /*
  43. 初始化一个io操作队列
  44. @api ioqueue.init(hwtimer_id,cmd_cnt,repeat_cnt)
  45. @int 硬件定时器id,默认用0,根据实际MCU确定,air105为0~5,与pwm共用,同一个通道号不能同时为pwm和ioqueue
  46. @int 一个完整周期需要的命令,可以比实际的多
  47. @int 重复次数,默认是1,如果写0则表示无限次数循环
  48. @return nil 无返回值
  49. @usage
  50. ioqueue.init(0,10,5) --以timer0为时钟源初始化一个io操作队列,有10个有效命令,循环5次
  51. */
  52. static int l_io_queue_init(lua_State *L) {
  53. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  54. int cmd_cnt = luaL_optinteger(L, 2, 0);
  55. int repeat_cnt = luaL_optinteger(L, 3, 1);
  56. luat_io_queue_init(timer_id, cmd_cnt, repeat_cnt);
  57. return 0;
  58. }
  59. /*
  60. 对io操作队列增加延时命令
  61. @api ioqueue.setdelay(hwtimer_id,time_us,time_tick,continue)
  62. @int 硬件定时器id
  63. @int 延时时间,0~65535us
  64. @int 延时微调时间,0~255tick,总的延时时间是time_us * 1us_tick + time_tick
  65. @boolean 是否连续是连续延时,默认否,如果是,定时器在时间到后不会停止而是重新计时,
  66. 从而实现在下一个setdelay命令前,每次调用delay都会重复相同时间延时,提高连续定时的精度
  67. @return nil 无返回值
  68. @usage
  69. ioqueue.setdelay(0,10,0) --延时10us+0个tick
  70. ioqueue.setdelay(0,9,15,true) --延时9us+15个tick,在之后遇到delay命令时,会延时9us+15个tick
  71. */
  72. static int l_io_queue_set_delay(lua_State *L) {
  73. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  74. uint16_t us_delay = luaL_optinteger(L, 2, 1);
  75. uint8_t us_delay_tick = luaL_optinteger(L, 3, 0);
  76. uint8_t is_continue = 0;
  77. if (lua_isboolean(L, 4))
  78. {
  79. is_continue = lua_toboolean(L, 4);
  80. }
  81. luat_io_queue_set_delay(timer_id, us_delay, us_delay_tick, is_continue);
  82. return 0;
  83. }
  84. /*
  85. 对io操作队列增加一次重复延时,在前面必须有setdelay且是连续延时
  86. @api ioqueue.delay(hwtimer_id)
  87. @int 硬件定时器id
  88. @return nil 无返回值
  89. @usage
  90. ioqueue.setdelay(0,9,15,true) --延时9us+15个tick,在之后遇到delay命令时,会延时9us+15个tick
  91. ioqueue.delay(0)
  92. */
  93. static int l_io_queue_delay(lua_State *L) {
  94. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  95. luat_io_queue_repeat_delay(timer_id);
  96. return 0;
  97. }
  98. /*
  99. 对io操作队列增加设置gpio命令
  100. @api ioqueue.setgpio(hwtimer_id,pin,is_input,pull_mode,init_level)
  101. @int 硬件定时器id
  102. @int pin
  103. @boolean 是否是输入
  104. @int 上下拉模式,只能是0,gpio.PULLUP,gpio.PULLDOWN
  105. @int 初始输出电平
  106. @return nil 无返回值
  107. @usage
  108. ioqueue.setgpio(0,17,true,gpio.PULLUP,0) --GPIO17设置成上拉输入
  109. ioqueue.setgpio(0,17,false,0,1)--GPIO17设置成默认上下拉输出高电平
  110. */
  111. static int l_io_queue_set_gpio(lua_State *L) {
  112. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  113. uint8_t pin = luaL_checkinteger(L, 2);
  114. uint8_t pull_mode = luaL_optinteger(L, 4, 0);
  115. uint8_t init_level = luaL_optinteger(L, 5, 0);
  116. uint8_t is_input = 0;
  117. if (lua_isboolean(L, 3))
  118. {
  119. is_input = lua_toboolean(L, 3);
  120. }
  121. luat_io_queue_add_io_config(timer_id, pin, is_input, pull_mode, init_level);
  122. return 0;
  123. }
  124. /*
  125. 对io操作队列增加读取gpio命令
  126. @api ioqueue.input(hwtimer_id,pin)
  127. @int 硬件定时器id
  128. @int pin
  129. @return nil 无返回值
  130. @usage
  131. --- 对GPIO17进行输入读取
  132. ioqueue.input(0, 17)
  133. */
  134. static int l_io_queue_gpio_input(lua_State *L) {
  135. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  136. uint8_t pin = luaL_checkinteger(L, 2);
  137. luat_io_queue_add_io_in(timer_id, pin, NULL, NULL);
  138. return 0;
  139. }
  140. /*
  141. 对io操作队列增加输出GPIO命令
  142. @api ioqueue.output(hwtimer_id,pin,level)
  143. @int 硬件定时器id
  144. @int pin
  145. @int 输出电平
  146. @return nil 无返回值
  147. @usage
  148. -- 对GPIO17输出低电平
  149. ioqueue.output(0, 17, 0)
  150. */
  151. static int l_io_queue_gpio_output(lua_State *L) {
  152. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  153. uint8_t pin = luaL_checkinteger(L, 2);
  154. uint8_t level = luaL_optinteger(L, 3, 0);
  155. luat_io_queue_add_io_out(timer_id, pin, level);
  156. return 0;
  157. }
  158. /*
  159. 对io操作队列增加设置捕获某个IO命令
  160. @api ioqueue.set_cap(hwtimer_id,pin,pull_mode,irq_mode,max_tick)
  161. @int 硬件定时器id
  162. @int pin
  163. @int 上下拉模式,只能是0,gpio.PULLUP,gpio.PULLDOWN
  164. @int 中断模式,只能是gpio.BOTH,gpio.RISING,gpio.FALLING
  165. @int 定时器最大计时时间 考虑到lua是int类型,最小0x10000, 最大值为0x7fffffff,默认为最大值
  166. @return nil 无返回值
  167. @usage
  168. -- 捕获指令
  169. ioqueue.setcap(0, 17, gpio.PULLUP, gpio.FALLING, 48000000)
  170. */
  171. static int l_io_queue_set_capture(lua_State *L) {
  172. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  173. uint8_t pin = luaL_checkinteger(L, 2);
  174. uint8_t pull_mode = luaL_optinteger(L, 3, 0);
  175. uint8_t irq_mode = luaL_optinteger(L, 4, 0);
  176. int max_cnt = luaL_optinteger(L, 5, 0x7fffffff);
  177. if (max_cnt < 65536)
  178. {
  179. max_cnt = 65536;
  180. }
  181. luat_io_queue_capture_set(timer_id, max_cnt, pin, pull_mode, irq_mode);
  182. return 0;
  183. }
  184. /*
  185. 对io操作队列增加捕获一次IO状态命令
  186. @api ioqueue.capture(hwtimer_id)
  187. @int 硬件定时器id
  188. @return nil 无返回值
  189. @usage
  190. ioqueue.capture(0)
  191. */
  192. static int l_io_queue_capture_pin(lua_State *L) {
  193. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  194. luat_io_queue_capture(timer_id, NULL, NULL);
  195. return 0;
  196. }
  197. /*
  198. 对io操作队列增加结束捕获某个IO命令
  199. @api ioqueue.cap_done(hwtimer_id,pin)
  200. @int 硬件定时器id
  201. @int pin
  202. @return nil 无返回值
  203. @usage
  204. -- 结束捕获
  205. ioqueue.cap_done(0, 17)
  206. */
  207. static int l_io_queue_capture_end(lua_State *L) {
  208. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  209. uint8_t pin = luaL_checkinteger(L, 2);
  210. luat_io_queue_capture_end(timer_id, pin);
  211. return 0;
  212. }
  213. /*
  214. * 获取io操作队列中输入和捕获的数据
  215. @api ioqueue.get(hwtimer_id, input_buff, capture_buff)
  216. @int 硬件定时器id
  217. @zbuff 存放IO输入数据的buff,按照1byte pin + 1byte level 形式存放数据
  218. @zbuff 存放IO捕获数据的buff,按照1byte pin + 1byte level + 4byte tick形式存放数据
  219. @return int 返回多少组IO输入数据
  220. @return int 返回多少组IO捕获数据
  221. @usage
  222. local input_cnt, capture_cnt = ioqueue.get(0, input_buff, capture_buff)
  223. */
  224. static int l_io_queue_get(lua_State *L) {
  225. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  226. luat_zbuff_t *buff1 = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  227. luat_zbuff_t *buff2 = ((luat_zbuff_t *)luaL_checkudata(L, 3, LUAT_ZBUFF_TYPE));
  228. uint32_t input_cnt, capture_cnt;
  229. uint32_t size = luat_io_queue_get_size(timer_id);
  230. if (buff1->len < (size * 2)) __zbuff_resize(buff1, (size * 2));
  231. if (buff2->len < (size * 6)) __zbuff_resize(buff2, (size * 6));
  232. luat_io_queue_get_data(timer_id, buff1->addr, &input_cnt, buff2->addr, &capture_cnt);
  233. buff1->used = input_cnt * 2;
  234. buff2->used = capture_cnt * 6;
  235. lua_pushinteger(L, input_cnt);
  236. lua_pushinteger(L, capture_cnt);
  237. return 2;
  238. }
  239. /*
  240. 启动io操作队列
  241. @api ioqueue.start(hwtimer_id)
  242. @int 硬件定时器id
  243. @return nil 无返回值
  244. @usage
  245. ioqueue.start(0)
  246. */
  247. static int l_io_queue_start(lua_State *L) {
  248. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  249. luat_io_queue_start(timer_id);
  250. return 0;
  251. }
  252. /*
  253. 停止io操作队列,可以通过start从头开始
  254. @api ioqueue.stop(hwtimer_id)
  255. @int 硬件定时器id
  256. @return int 返回已经循环的次数,如果是0,表示一次循环都没有完成
  257. @return int 返回单次循环中已经执行的cmd次数,如果是0,可能是一次循环刚刚结束
  258. @usage
  259. ioqueue.stop(0)
  260. */
  261. static int l_io_queue_stop(lua_State *L) {
  262. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  263. uint32_t repeat_cnt = 0;
  264. uint32_t cmd_cnt = 0;
  265. luat_io_queue_stop(timer_id, &repeat_cnt, &cmd_cnt);
  266. lua_pushinteger(L, repeat_cnt);
  267. lua_pushinteger(L, cmd_cnt);
  268. return 2;
  269. }
  270. /*
  271. 释放io操作队列的资源,下次使用必须重新init
  272. @api ioqueue.release(hwtimer_id)
  273. @int 硬件定时器id
  274. @return nil 无返回值
  275. @usage
  276. ioqueue.clear(0)
  277. */
  278. static int l_io_queue_release(lua_State *L) {
  279. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  280. luat_io_queue_release(timer_id);
  281. return 0;
  282. }
  283. /*
  284. 清空io操作队列
  285. @api ioqueue.clear(hwtimer_id)
  286. @int 硬件定时器id
  287. @return nil 无返回值
  288. @usage
  289. ioqueue.clear(0)
  290. */
  291. static int l_io_queue_clear(lua_State *L) {
  292. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  293. luat_io_queue_clear(timer_id);
  294. return 0;
  295. }
  296. /*
  297. 检测io操作队列是否已经执行完成
  298. @api ioqueue.done(hwtimer_id)
  299. @int 硬件定时器id
  300. @return boolean 队列是否执行完成,
  301. @usage
  302. local result = ioqueue.done(0)
  303. */
  304. static int l_io_queue_is_done(lua_State *L) {
  305. uint8_t timer_id = luaL_optinteger(L, 1, 0);
  306. lua_pushboolean(L, luat_io_queue_check_done(timer_id));
  307. return 1;
  308. }
  309. /*
  310. 启动/停止一个带系统tick返回的外部中断
  311. @api ioqueue.exti(pin,pull_mode,irq_mode,onoff)
  312. @int pin
  313. @int 上下拉模式,只能是0,gpio.PULLUP,gpio.PULLDOWN
  314. @int 中断模式,只能是gpio.BOTH,gpio.RISING,gpio.FALLING
  315. @boolean 开关,默认是false关
  316. @return nil 无返回值
  317. @usage
  318. -- 对GPIO17进行外部中断捕获
  319. ioqueue.exti(17, gpio.PULLUP, gpio.BOTH, true)
  320. ioqueue.exti(17)
  321. */
  322. static int l_io_queue_exti(lua_State *L) {
  323. uint8_t pin = luaL_checkinteger(L, 1);
  324. uint8_t pull_mode = luaL_optinteger(L, 2, 0);
  325. uint8_t irq_mode = luaL_optinteger(L, 3, 0);
  326. uint8_t on_off = 0;
  327. if (lua_isboolean(L, 4)) {
  328. on_off = lua_toboolean(L, 4);
  329. }
  330. if (on_off) {
  331. luat_io_queue_capture_start_with_sys_tick(pin, pull_mode, irq_mode);
  332. } else {
  333. luat_io_queue_capture_end_with_sys_tick(pin);
  334. }
  335. return 0;
  336. }
  337. #include "rotable2.h"
  338. static const rotable_Reg_t reg_io_queue[] =
  339. {
  340. { "init" , ROREG_FUNC(l_io_queue_init)},
  341. { "setdelay" , ROREG_FUNC(l_io_queue_set_delay)},
  342. { "delay" , ROREG_FUNC(l_io_queue_delay)},
  343. { "setgpio", ROREG_FUNC(l_io_queue_set_gpio)},
  344. { "input", ROREG_FUNC(l_io_queue_gpio_input)},
  345. { "output", ROREG_FUNC(l_io_queue_gpio_output)},
  346. { "set_cap", ROREG_FUNC(l_io_queue_set_capture)},
  347. { "capture", ROREG_FUNC(l_io_queue_capture_pin)},
  348. { "cap_done", ROREG_FUNC(l_io_queue_capture_end)},
  349. { "clear", ROREG_FUNC(l_io_queue_clear)},
  350. { "start", ROREG_FUNC(l_io_queue_start)},
  351. { "stop", ROREG_FUNC(l_io_queue_stop)},
  352. { "done", ROREG_FUNC(l_io_queue_is_done)},
  353. { "get", ROREG_FUNC(l_io_queue_get)},
  354. { "release", ROREG_FUNC(l_io_queue_release)},
  355. { "exti", ROREG_FUNC(l_io_queue_exti)},
  356. { NULL, ROREG_INT(0)}
  357. };
  358. LUAMOD_API int luaopen_io_queue( lua_State *L ) {
  359. luat_newlib2(L, reg_io_queue);
  360. return 1;
  361. }