main.lua 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. -- LuaTools需要PROJECT和VERSION这两个信息
  2. PROJECT = "testtts"
  3. VERSION = "2.0.0"
  4. --[[
  5. 本demo当前仅支持ec618系列和ec718系列
  6. ## 提醒:
  7. 1. 本demo需要2022.12.21及之后的源码所编译的LuatOS固件
  8. 2. 本demo若使用外置TTS资源的LuatOS固件, 就必须有外挂的SPI Flash, 起码1M字节, 后面有刷写说明
  9. 3. 下载脚本时, 把txt也加上一起下载
  10. 4. 本demo需要音频扩展板, 780E只有I2S输出, 需要codec和PA才能驱动喇叭
  11. 5. 内置TTS资源的LuatOS最低版本是V1104,且去掉了很多库, 尤其是UI方面的库
  12. ## 使用本demo前,如果是外置TTS资源的LuatOS固件, 必须先刷tts.binpkg进行SPI Flash的刷写
  13. 1. 下载链接:
  14. 618系列:https://gitee.com/openLuat/luatos-soc-2022/attach_files
  15. 718系列:https://gitee.com/openLuat/luatos-soc-2023/attach_files
  16. 2. 在LuaTools主界面, 用"下载固件"按钮进行下载.
  17. 3. 下载前需要接好SPI Flash!!
  18. 4. 下载前选日志模式 4G USB, luatools版本号2.1.85或以上
  19. ## SPI Flash布局, 以1M字节为例,供参考:
  20. -----------------------------------
  21. 64 k 保留空间, 用户自行分配
  22. -----------------------------------
  23. 704k TTS数据
  24. -----------------------------------
  25. 剩余空间, 256k,用户自行分配
  26. -----------------------------------
  27. ## 基本流程:
  28. 1. 初始化sfud, 本demo使用SPI0 + GPIO8
  29. 2. 使用 audio.tts播放文本
  30. 3. 等待 播放结束事件
  31. 4. 从第二步重新下一个循环
  32. ## 接线说明
  33. 以780E开发板为例, 需要1.5版本或以上,团购版本均为1.5或以上.
  34. 1.4版本SPI分布有所不同, 注意区分.
  35. https://wiki.luatos.com/chips/air780e/board.html
  36. xx脚指开发板pinout图上的顺序编号, 非GPIO编号
  37. Flash -- 开发板
  38. GND -- 16脚, GND
  39. VCC -- 15脚, 3.3V
  40. CLK -- 14脚, GPIO11/SPI0_CLK/LCD_CLK, 时钟. 如果是1.4版本的开发板, 接05脚的GPIO11/UART2_TXD
  41. MOSI -- 13脚, GPIO09/SPI0_MOSI/LCD_OUT,主控数据输出
  42. MISO -- 11脚, GPIO10/SPI0_MISO/LCD_RS,主控数据输入. 如果是1.4版本的开发板, 接06脚的GPIO10/UART2_RXD
  43. CS -- 10脚, GPIO08/SPI0_CS/LCD_CS,片选.
  44. 注意: 12脚是跳过的, 接线完毕后请检查好再通电!!
  45. ]]
  46. -- sys库是标配
  47. _G.sys = require("sys")
  48. _G.sysplus = require("sysplus")
  49. -- Air780E的AT固件默认会为开机键防抖, 导致部分用户刷机很麻烦
  50. if rtos.bsp() == "EC618" and pm and pm.PWK_MODE then
  51. pm.power(pm.PWK_MODE, false)
  52. end
  53. function audio_setup()
  54. local bsp = rtos.bsp()
  55. if bsp == "EC618" then
  56. --Air780E开发板配套+音频扩展板. ES7149
  57. --由于音频扩展板的PA是长供电的,有塔塔声音是正常的,做产品的话有额外的参考设计
  58. i2s.setup(0, 0, 0, 0, 0, i2s.MODE_I2S)
  59. --如果用TM8211,打开下面的注释
  60. -- i2s.setup(0, 0, 0, 0, 0, i2s.MODE_MSB)
  61. --如果用软件DAC,打开下面的注释
  62. -- if audio.setBus then
  63. -- audio.setBus(0, audio.BUS_SOFT_DAC)
  64. -- end
  65. audio.config(0, 25, 1, 3, 100)
  66. elseif string.find(bsp,"EC718") then
  67. -- CORE+音频小板是这个配置
  68. pm.power(pm.LDO_CTL, false) --开发板上ES8311由LDO_CTL控制上下电
  69. sys.wait(100)
  70. pm.power(pm.LDO_CTL, true) --开发板上ES8311由LDO_CTL控制上下电
  71. local multimedia_id = 0
  72. local i2c_id = 0
  73. local i2s_id = 0
  74. local i2s_mode = 0
  75. local i2s_sample_rate = 16000
  76. local i2s_bits_per_sample = 16
  77. local i2s_channel_format = i2s.MONO_R
  78. local i2s_communication_format = i2s.MODE_LSB
  79. local i2s_channel_bits = 16
  80. local pa_pin = 25
  81. local pa_on_level = 1
  82. local pa_delay = 100
  83. local power_pin = 255
  84. local power_on_level = 1
  85. local power_delay = 3
  86. local power_time_delay = 100
  87. local voice_vol = 70
  88. local mic_vol = 80
  89. i2c.setup(i2c_id,i2c.FAST)
  90. i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, i2s_bits_per_sample, i2s_channel_format, i2s_communication_format,i2s_channel_bits)
  91. audio.config(multimedia_id, pa_pin, pa_on_level, power_delay, pa_delay, power_pin, power_on_level, power_time_delay)
  92. audio.setBus(multimedia_id, audio.BUS_I2S,{chip = "es8311",i2cid = i2c_id , i2sid = i2s_id}) --通道0的硬件输出通道设置为I2S
  93. audio.vol(multimedia_id, voice_vol)
  94. audio.micVol(multimedia_id, mic_vol)
  95. --带TM8211的云喇叭开发板参考下面的配置
  96. --[[
  97. local multimedia_id = 0
  98. local i2s_id = 0
  99. local i2s_mode = 0
  100. local i2s_sample_rate = 0
  101. local i2s_bits_per_sample = 16
  102. local i2s_channel_format = i2s.STEREO
  103. local i2s_communication_format = i2s.MODE_MSB
  104. local i2s_channel_bits = 16
  105. local pa_pin = 25
  106. local pa_on_level = 1
  107. local pa_delay = 100
  108. local power_pin = nil
  109. local power_on_level = 1
  110. local power_delay = 3
  111. local power_time_delay = 0
  112. -- local voice_vol = 200 --默认就不放大了
  113. i2s.setup(i2s_id, i2s_mode, i2s_sample_rate, i2s_bits_per_sample, i2s_channel_format, i2s_communication_format,i2s_channel_bits)
  114. audio.config(multimedia_id, pa_pin, pa_on_level, power_delay, pa_delay, power_pin, power_on_level, power_time_delay)
  115. audio.setBus(multimedia_id, audio.BUS_I2S,{chip = "tm8211", i2sid = i2s_id}) --通道0的硬件输出通道设置为I2S
  116. -- audio.vol(multimedia_id, voice_vol)
  117. ]]
  118. elseif bsp == "AIR105" then
  119. -- Air105开发板支持DAC直接输出
  120. audio.config(0, 25, 1, 3, 100)
  121. else
  122. -- 其他板子未支持
  123. while 1 do
  124. log.info("audio", "尚未支持的BSP")
  125. sys.wait(1000)
  126. end
  127. end
  128. sys.publish("AUDIO_READY")
  129. end
  130. -- 配置好audio外设
  131. sys.taskInit(audio_setup)
  132. local taskName = "task_audio"
  133. local MSG_MD = "moreData" -- 播放缓存有空余
  134. local MSG_PD = "playDone" -- 播放完成所有数据
  135. audio.on(0, function(id, event)
  136. --使用play来播放文件时只有播放完成回调
  137. local succ,stop,file_cnt = audio.getError(0)
  138. if not succ then
  139. if stop then
  140. log.info("用户停止播放")
  141. else
  142. log.info("第", file_cnt, "个文件解码失败")
  143. end
  144. end
  145. sysplus.sendMsg(taskName, MSG_PD)
  146. end)
  147. local function audio_task()
  148. local result
  149. sys.waitUntil("AUDIO_READY")
  150. -- 初始化spi flash, 如果是极限版TTS_ONCHIP,就不需要初始化
  151. if sfud then
  152. spi_flash = spi.deviceSetup(0,8,0,0,8,25600000,spi.MSB,1,0)
  153. local ret = sfud.init(spi_flash)
  154. if ret then
  155. log.info("sfud.init ok")
  156. else
  157. log.info("sfud.init error", ret)
  158. return
  159. end
  160. else
  161. log.info("tts", "TTS_ONCHIP?? skip sfud")
  162. end
  163. -- 本例子是按行播放 "千字文", 文本来源自wiki百科
  164. local fd = nil
  165. local line = nil
  166. while true do
  167. log.info("开始播放")
  168. line = nil
  169. if not fd then
  170. fd = io.open("/luadb/qianzw.txt")
  171. end
  172. if fd then
  173. line = fd:read("*l")
  174. if line == nil then
  175. fd:close()
  176. fd = nil
  177. end
  178. end
  179. if line == nil then
  180. line = "一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十一二三四五六七八九十"
  181. end
  182. line = line:trim()
  183. log.info("播放内容", line)
  184. result = audio.tts(0, line)
  185. if result then
  186. --等待音频通道的回调消息,或者切换歌曲的消息
  187. while true do
  188. msg = sysplus.waitMsg(taskName, nil)
  189. if type(msg) == 'table' then
  190. if msg[1] == MSG_PD then
  191. log.info("播放结束")
  192. break
  193. end
  194. else
  195. log.error(type(msg), msg)
  196. end
  197. end
  198. else
  199. log.debug("解码失败!")
  200. sys.wait(1000)
  201. end
  202. if not audio.isEnd(0) then
  203. log.info("手动关闭")
  204. audio.playStop(0)
  205. end
  206. if audio.pm then
  207. audio.pm(0,audio.STANDBY)
  208. end
  209. -- audio.pm(0,audio.SHUTDOWN) --低功耗可以选择SHUTDOWN或者POWEROFF,如果codec无法断电用SHUTDOWN
  210. log.info("mem", "sys", rtos.meminfo("sys"))
  211. log.info("mem", "lua", rtos.meminfo("lua"))
  212. sys.wait(1000)
  213. end
  214. sysplus.taskDel(taskName)
  215. end
  216. sysplus.taskInitEx(audio_task, taskName, task_cb)
  217. -- 用户代码已结束---------------------------------------------
  218. -- 结尾总是这一句
  219. sys.run()
  220. -- sys.run()之后后面不要加任何语句!!!!!