luat_lib_io_queue.c 11 KB

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