luat_i2s_air101.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include "luat_base.h"
  2. #include "luat_i2s.h"
  3. #include "wm_include.h"
  4. #include "wm_i2s.h"
  5. #include "wm_gpio_afsel.h"
  6. #include "c_common.h"
  7. #define LUAT_LOG_TAG "i2s"
  8. #include "luat_log.h"
  9. #define AUDIO_BUF_SIZE (1024 * 10)
  10. #define PERIOD_PLAY 64
  11. static uint8_t i2s_tx_buffer[PERIOD_PLAY];
  12. static wm_dma_handler_type dma_tx;
  13. static Buffer_Struct dma_tx_buf;
  14. #define CODEC_RUNING (1 << 0)
  15. volatile uint8_t run_status = 0;
  16. static int I2s_tx_send(){
  17. uint16_t send_bytes;
  18. if (PERIOD_PLAY>dma_tx_buf.Pos){
  19. send_bytes = dma_tx_buf.Pos;
  20. }else{
  21. send_bytes = PERIOD_PLAY;
  22. }
  23. memcpy(i2s_tx_buffer, dma_tx_buf.Data, send_bytes);
  24. OS_BufferRemove(&dma_tx_buf, send_bytes);
  25. if(send_bytes == 0)
  26. return -1;
  27. DMA_SRCADDR_REG(dma_tx.channel) = (uint32_t )i2s_tx_buffer;
  28. DMA_CTRL_REG(dma_tx.channel) &= ~0xFFFF00;
  29. DMA_CTRL_REG(dma_tx.channel) |= (send_bytes<<8);
  30. DMA_CHNLCTRL_REG(dma_tx.channel) = DMA_CHNL_CTRL_CHNL_ON;
  31. wm_i2s_tx_dma_enable(1);
  32. wm_i2s_tx_enable(1);
  33. wm_i2s_enable(1);
  34. return 0;
  35. }
  36. static void I2s_dma_tx_irq(void *p){
  37. int ret_len = dma_tx_buf.Pos;
  38. if(ret_len >= 4 ){
  39. I2s_tx_send();
  40. }else{
  41. run_status &= ~CODEC_RUNING;
  42. }
  43. }
  44. static int I2s_tx_dma_init(void){
  45. if (dma_tx_buf.Data){
  46. return 0;
  47. }
  48. OS_InitBuffer(&dma_tx_buf, AUDIO_BUF_SIZE);
  49. memset(&dma_tx, 0, sizeof(wm_dma_handler_type));
  50. if(dma_tx.channel){
  51. tls_dma_free(dma_tx.channel);
  52. }
  53. dma_tx.channel = tls_dma_request(WM_I2S_TX_DMA_CHANNEL, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_I2S_TX) | TLS_DMA_FLAGS_HARD_MODE);
  54. if(dma_tx.channel == 0){
  55. return -1;
  56. }
  57. if (tls_dma_stop(dma_tx.channel)){
  58. return -1;
  59. }
  60. tls_dma_irq_register(dma_tx.channel, I2s_dma_tx_irq, &dma_tx, TLS_DMA_IRQ_TRANSFER_DONE);
  61. DMA_INTMASK_REG &= ~(0x02<<(dma_tx.channel*2));
  62. DMA_DESTADDR_REG(dma_tx.channel) = HR_I2S_TX;
  63. DMA_CTRL_REG(dma_tx.channel) = DMA_CTRL_SRC_ADDR_INC | DMA_CTRL_DATA_SIZE_WORD | DMA_CTRL_BURST_SIZE1;
  64. DMA_MODE_REG(dma_tx.channel) = DMA_MODE_SEL_I2S_TX | DMA_MODE_HARD_MODE;
  65. DMA_CTRL_REG(dma_tx.channel) &= ~0xFFFF00;
  66. return 0;
  67. }
  68. static int tls_i2s_io_init(void){
  69. wm_i2s_ck_config(WM_IO_PB_08);
  70. wm_i2s_ws_config(WM_IO_PB_09);
  71. wm_i2s_di_config(WM_IO_PB_10);
  72. wm_i2s_do_config(WM_IO_PB_11);
  73. wm_i2s_extclk_config(WM_IO_PA_07);
  74. LLOGD("ck--PB08, ws--PB09, di--PB10, do--PB11, mclk--PA07");
  75. return WM_SUCCESS;
  76. }
  77. luat_i2s_conf_t i2s_conf;
  78. int luat_i2s_setup(luat_i2s_conf_t *conf) {
  79. if (I2s_tx_dma_init()){
  80. return -1;
  81. }
  82. memcpy(&i2s_conf, conf, sizeof(luat_i2s_conf_t));
  83. tls_i2s_io_init();
  84. // 然后转本地i2s配置
  85. I2S_InitDef opts = { I2S_MODE_MASTER, I2S_CTRL_STEREO, I2S_RIGHT_CHANNEL, I2S_Standard, I2S_DataFormat_16, 8000, 5000000 };
  86. uint8_t stereo = 1;
  87. opts.I2S_Mode_MS = I2S_MODE_MASTER;
  88. opts.I2S_Mode_SS = (stereo<<22);
  89. opts.I2S_Mode_LR = conf->channel_format==0?I2S_LEFT_CHANNEL : I2S_RIGHT_CHANNEL;
  90. opts.I2S_Trans_STD = (conf->communication_format*0x1000000);
  91. opts.I2S_DataFormat = (conf->bits_per_sample/8 - 1)*0x10;
  92. opts.I2S_AudioFreq = conf->sample_rate;
  93. opts.I2S_MclkFreq = conf->mclk;
  94. wm_i2s_port_init(&opts);
  95. // wm_i2s_register_callback(NULL);
  96. run_status = 0;
  97. return 0;
  98. }
  99. int luat_i2s_send(uint8_t id, char* buff, size_t len) {
  100. int ret;
  101. if (buff == NULL) {
  102. return -1;
  103. }
  104. if (len == 0) {
  105. return 0;
  106. }
  107. OS_BufferWrite(&dma_tx_buf, buff, len);
  108. if ((run_status & CODEC_RUNING) == 0) {
  109. run_status |= CODEC_RUNING;
  110. ret = I2s_tx_send();
  111. if(ret == -1){
  112. LLOGE("fifo empty for send\n");
  113. run_status &= ~CODEC_RUNING;
  114. return 0;
  115. }
  116. }
  117. return len;
  118. }
  119. int luat_i2s_recv(uint8_t id, char* buff, size_t len) {
  120. wm_i2s_rx_int((int16_t *)buff, len / 2);
  121. return len;
  122. }
  123. int luat_i2s_resume(uint8_t id) {
  124. wm_i2s_tx_enable(1);
  125. return 0;
  126. }
  127. int luat_i2s_stop(uint8_t id) {
  128. wm_i2s_tx_enable(0);
  129. run_status = 0;
  130. return 0;
  131. }
  132. int luat_i2s_close(uint8_t id) {
  133. luat_i2s_stop(id);
  134. if(dma_tx.channel){
  135. tls_dma_free(dma_tx.channel);
  136. }
  137. if (dma_tx_buf.Data){
  138. OS_DeInitBuffer(&dma_tx_buf);
  139. }
  140. return 0;
  141. }
  142. int luat_i2s_tx_stat(uint8_t id, size_t *buffsize, size_t* remain) {
  143. *buffsize = AUDIO_BUF_SIZE;
  144. *remain = dma_tx_buf.Pos;
  145. return 0;
  146. }