luat_lib_i2s.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. @module i2s
  3. @summary 数字音频
  4. @version core V0007
  5. @date 2022.05.26
  6. @tag LUAT_USE_I2S
  7. */
  8. #include "luat_base.h"
  9. #include "luat_malloc.h"
  10. #include "luat_i2s.h"
  11. #include "luat_zbuff.h"
  12. #include "c_common.h"
  13. #define LUAT_LOG_TAG "i2s"
  14. #include "luat_log.h"
  15. #ifndef I2S_DEVICE_MAX_CNT
  16. #define I2S_DEVICE_MAX_CNT 2
  17. #endif
  18. static int i2s_cbs[I2S_DEVICE_MAX_CNT];
  19. static luat_zbuff_t *i2s_rx_buffer[I2S_DEVICE_MAX_CNT];
  20. int l_i2s_handler(lua_State *L, void* ptr) {
  21. (void)ptr;
  22. //LLOGD("l_uart_handler");
  23. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  24. lua_pop(L, 1);
  25. int i2s_id = msg->arg1;
  26. lua_geti(L, LUA_REGISTRYINDEX, i2s_cbs[i2s_id]);
  27. if (lua_isfunction(L, -1)) {
  28. if (msg->arg2 == 0) {
  29. //LLOGD("uart%ld sent callback", i2s_id);
  30. lua_pushinteger(L, i2s_id);
  31. lua_pushnil(L);
  32. lua_call(L, 2, 0);
  33. }
  34. else {
  35. lua_pushinteger(L, i2s_id);
  36. lua_pushlightuserdata(L, i2s_rx_buffer[i2s_id]);
  37. lua_call(L, 2, 0);
  38. }
  39. }
  40. // 给rtos.recv方法返回个空数据
  41. lua_pushinteger(L, 0);
  42. return 1;
  43. }
  44. int32_t luat_i2s_rx_cb(void *pdata, void *param)
  45. {
  46. Buffer_Struct *buffer = (Buffer_Struct *)pdata;
  47. int id = (int)param;
  48. if (!i2s_rx_buffer[id] || !i2s_cbs[id])
  49. {
  50. return -1;
  51. }
  52. if (buffer && (buffer->Pos))
  53. {
  54. uint32_t len = (buffer->Pos > i2s_rx_buffer[id]->len)?i2s_rx_buffer[id]->len:buffer->Pos;
  55. memcpy(i2s_rx_buffer[id]->addr, buffer->Data, len);
  56. i2s_rx_buffer[id]->used = len;
  57. rtos_msg_t msg;
  58. msg.handler = l_i2s_handler;
  59. msg.ptr = NULL;
  60. msg.arg1 = id;
  61. msg.arg2 = len;
  62. int re = luat_msgbus_put(&msg, 0);
  63. buffer->Pos = 0;
  64. }
  65. return 0;
  66. }
  67. /*
  68. 初始化i2s
  69. @api i2s.setup(id, mode, sample, bitw, channel, format, mclk)
  70. @int i2s通道号,与具体设备有关
  71. @int 模式, 当前仅支持0, MASTER|TX|RX 模式, 暂不支持slave. 可选
  72. @int 采样率,默认44100. 可选
  73. @int 声道, 0 左声道, 1 右声道, 2 双声道. 可选
  74. @int 格式, 可选MODE_I2S, MODE_LSB, MODE_MSB
  75. @int mclk频率, 默认 8M. 可选
  76. @return boolean 成功与否
  77. @return int 底层返回值
  78. @usage
  79. -- 这个库处于开发阶段, 尚不可用
  80. -- 以默认参数初始化i2s
  81. i2s.setup(0)
  82. -- 以详细参数初始化i2s, 示例为默认值
  83. i2s.setup(0, 0, 44100, 16, 0, 0, 8000000)
  84. */
  85. static int l_i2s_setup(lua_State *L) {
  86. luat_i2s_conf_t conf = {0};
  87. conf.id = luaL_checkinteger(L, 1);
  88. conf.mode = luaL_optinteger(L, 2, 0);
  89. conf.sample_rate = luaL_optinteger(L, 3, 44100); // 44.1k比较常见吧,待讨论
  90. conf.bits_per_sample = luaL_optinteger(L, 4, 16); // 通常就是16bit
  91. conf.channel_format = luaL_optinteger(L, 5, 0); // 1 右声道, 0 左声道
  92. conf.communication_format = luaL_optinteger(L, 6, 0); // 0 - I2S 标准, 当前只支持这种就行
  93. conf.mclk = luaL_optinteger(L, 7, 0);
  94. // conf.intr_alloc_flags = luaL_optinteger(L, 8, 0);
  95. int ret = luat_i2s_setup(&conf);
  96. lua_pushboolean(L, ret == 0 ? 1 : 0);
  97. lua_pushinteger(L, ret);
  98. return 2;
  99. }
  100. /*
  101. 发送i2s数据
  102. @api i2s.send(id, data, len)
  103. @int 通道id
  104. @string 数据, 可以是字符串或zbuff
  105. @int 数据长度,单位字节, 字符串默认为字符串全长, zbuff默认为指针位置
  106. @return boolean 成功与否
  107. @return int 底层返回值,供调试用
  108. @usage
  109. local f = io.open("/luadb/abc.wav")
  110. while 1 do
  111. local data = f:read(4096)
  112. if not data or #data == 0 then
  113. break
  114. end
  115. i2s.send(0, data)
  116. sys.wait(100)
  117. end
  118. */
  119. static int l_i2s_send(lua_State *L) {
  120. char* buff;
  121. size_t len;
  122. int id = luaL_checkinteger(L, 1);
  123. if (lua_isuserdata(L, 2)) {
  124. luat_zbuff_t* zbuff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  125. buff = (char*)zbuff->addr;
  126. len = zbuff->cursor;
  127. }
  128. else {
  129. buff = (char*)luaL_checklstring(L, 2, &len);
  130. }
  131. if (lua_type(L, 3) == LUA_TINTEGER) {
  132. len = luaL_checkinteger(L, 3);
  133. }
  134. int ret = luat_i2s_send(id, buff, len);
  135. lua_pushboolean(L, ret == len ? 1 : 0);
  136. lua_pushinteger(L, ret);
  137. return 2;
  138. }
  139. /*
  140. 接收i2s数据,注意在数据在回调时已经存放在zbuff里,目前只有air780e系列支持
  141. @api i2s.recv(id, buffer, len)
  142. @int 通道id
  143. @zbuff 数据缓存区
  144. @int 单次返回的数据长度,单位字节,必须与传入的zbuff的大小一致
  145. @return boolean 成功与否
  146. @usage
  147. local buffer = zbuff.create(3200)
  148. local succ = i2s.recv(0, buffer, 3200);
  149. */
  150. static int l_i2s_recv(lua_State *L) {
  151. luaL_Buffer buff;
  152. int id = luaL_checkinteger(L, 1);
  153. if (id >= I2S_DEVICE_MAX_CNT)
  154. {
  155. lua_pushboolean(L, 0);
  156. return 1;
  157. }
  158. if (lua_isuserdata(L, 2)) {
  159. luat_zbuff_t* zbuff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
  160. i2s_rx_buffer[id] = zbuff;
  161. }
  162. else {
  163. i2s_rx_buffer[id] = NULL;
  164. }
  165. size_t len = luaL_checkinteger(L, 3);
  166. lua_pushboolean(L, !luat_i2s_recv(id, NULL, len));
  167. return 1;
  168. }
  169. /*
  170. 关闭i2s
  171. @api i2s.close(id)
  172. @int 通道id
  173. @return nil 无返回值
  174. @usage
  175. i2s.close(0)
  176. */
  177. static int l_i2s_close(lua_State *L) {
  178. int id = luaL_checkinteger(L, 1);
  179. luat_i2s_close(id);
  180. return 0;
  181. }
  182. /*
  183. 注册I2S事件回调
  184. @api i2s.on(id, func)
  185. @int i2s id, i2s0写0, i2s1写1
  186. @function 回调方法
  187. @return nil 无返回值
  188. @usage
  189. i2s.on(0, function(id, buff)
  190. if buff then
  191. log.info("i2s get data in zbuff")
  192. else
  193. log.info("i2s tx one block done")
  194. end
  195. end)
  196. */
  197. static int l_i2s_on(lua_State *L) {
  198. int i2s_id = luaL_checkinteger(L, 1);
  199. if (i2s_id >= I2S_DEVICE_MAX_CNT)
  200. {
  201. lua_pushliteral(L, "no such i2s id");
  202. return 1;
  203. }
  204. if (i2s_cbs[i2s_id] != 0)
  205. {
  206. luaL_unref(L, LUA_REGISTRYINDEX, i2s_cbs[i2s_id]);
  207. }
  208. if (lua_isfunction(L, 2)) {
  209. lua_pushvalue(L, 2);
  210. i2s_cbs[i2s_id] = luaL_ref(L, LUA_REGISTRYINDEX);
  211. }
  212. return 0;
  213. }
  214. int l_i2s_play(lua_State *L);
  215. int l_i2s_pause(lua_State *L);
  216. int l_i2s_stop(lua_State *L);
  217. #ifndef LUAT_COMPILER_NOWEAK
  218. LUAT_WEAK int l_i2s_play(lua_State *L) {
  219. LLOGE("not support yet");
  220. return 0;
  221. }
  222. LUAT_WEAK int l_i2s_pause(lua_State *L) {
  223. LLOGE("not support yet");
  224. return 0;
  225. }
  226. LUAT_WEAK int l_i2s_stop(lua_State *L) {
  227. LLOGE("not support yet");
  228. return 0;
  229. }
  230. #endif
  231. #include "rotable2.h"
  232. static const rotable_Reg_t reg_i2s[] =
  233. {
  234. { "setup", ROREG_FUNC(l_i2s_setup)},
  235. { "send", ROREG_FUNC(l_i2s_send)},
  236. { "recv", ROREG_FUNC(l_i2s_recv)},
  237. { "close", ROREG_FUNC(l_i2s_close)},
  238. { "on", ROREG_FUNC(l_i2s_on)},
  239. // 以下为兼容扩展功能,待定
  240. { "play", ROREG_FUNC(l_i2s_play)},
  241. { "pause", ROREG_FUNC(l_i2s_pause)},
  242. { "stop", ROREG_FUNC(l_i2s_stop)},
  243. //@const MODE_I2S number I2S标准,比如ES7149
  244. { "MODE_I2S", ROREG_INT(0)},
  245. //@const MODE_LSB number LSB格式
  246. { "MODE_LSB", ROREG_INT(1)},
  247. //@const MODE_MSB number MSB格式,比如TM8211
  248. { "MODE_MSB", ROREG_INT(2)},
  249. { NULL, ROREG_INT(0) }
  250. };
  251. LUAMOD_API int luaopen_i2s(lua_State *L)
  252. {
  253. luat_newlib2(L, reg_i2s);
  254. return 1;
  255. }