luat_i2s_air101.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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 luat_i2s_conf_t i2s_conf = {0}; // 记录i2s配置信息
  13. static wm_dma_handler_type dma_tx;
  14. static Buffer_Struct dma_tx_buf;
  15. #define CODEC_RUNING (1 << 0)
  16. // volatile uint8_t run_status = 0;
  17. static int I2s_tx_send(){
  18. uint16_t send_bytes;
  19. if (PERIOD_PLAY>dma_tx_buf.Pos){
  20. send_bytes = dma_tx_buf.Pos;
  21. }else{
  22. send_bytes = PERIOD_PLAY;
  23. }
  24. memcpy(i2s_tx_buffer, dma_tx_buf.Data, send_bytes);
  25. OS_BufferRemove(&dma_tx_buf, send_bytes);
  26. if(send_bytes == 0)
  27. return -1;
  28. DMA_SRCADDR_REG(dma_tx.channel) = (uint32_t )i2s_tx_buffer;
  29. DMA_CTRL_REG(dma_tx.channel) &= ~0xFFFF00;
  30. DMA_CTRL_REG(dma_tx.channel) |= (send_bytes<<8);
  31. DMA_CHNLCTRL_REG(dma_tx.channel) = DMA_CHNL_CTRL_CHNL_ON;
  32. wm_i2s_tx_dma_enable(1);
  33. wm_i2s_tx_enable(1);
  34. wm_i2s_enable(1);
  35. return 0;
  36. }
  37. static void I2s_dma_tx_irq(void *p){
  38. int ret_len = dma_tx_buf.Pos;
  39. if(ret_len >= 4 ){
  40. I2s_tx_send();
  41. }else{
  42. i2s_conf.state = LUAT_I2S_STATE_STOP;
  43. }
  44. }
  45. static int I2s_tx_dma_init(void){
  46. if (dma_tx_buf.Data){
  47. return 0;
  48. }
  49. OS_InitBuffer(&dma_tx_buf, AUDIO_BUF_SIZE);
  50. memset(&dma_tx, 0, sizeof(wm_dma_handler_type));
  51. if(dma_tx.channel){
  52. tls_dma_free(dma_tx.channel);
  53. }
  54. 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);
  55. if(dma_tx.channel == 0){
  56. return -1;
  57. }
  58. if (tls_dma_stop(dma_tx.channel)){
  59. return -1;
  60. }
  61. tls_dma_irq_register(dma_tx.channel, I2s_dma_tx_irq, &dma_tx, TLS_DMA_IRQ_TRANSFER_DONE);
  62. DMA_INTMASK_REG &= ~(0x02<<(dma_tx.channel*2));
  63. DMA_DESTADDR_REG(dma_tx.channel) = HR_I2S_TX;
  64. DMA_CTRL_REG(dma_tx.channel) = DMA_CTRL_SRC_ADDR_INC | DMA_CTRL_DATA_SIZE_WORD | DMA_CTRL_BURST_SIZE1;
  65. DMA_MODE_REG(dma_tx.channel) = DMA_MODE_SEL_I2S_TX | DMA_MODE_HARD_MODE;
  66. DMA_CTRL_REG(dma_tx.channel) &= ~0xFFFF00;
  67. return 0;
  68. }
  69. static int tls_i2s_io_init(void){
  70. wm_i2s_ck_config(WM_IO_PB_08);
  71. wm_i2s_ws_config(WM_IO_PB_09);
  72. wm_i2s_di_config(WM_IO_PB_10);
  73. wm_i2s_do_config(WM_IO_PB_11);
  74. wm_i2s_extclk_config(WM_IO_PA_07);
  75. LLOGD("ck--PB08, ws--PB09, di--PB10, do--PB11, mclk--PA07");
  76. return WM_SUCCESS;
  77. }
  78. luat_i2s_conf_t *luat_i2s_get_config(uint8_t id){
  79. if (id != 0) return NULL;
  80. return &i2s_conf;
  81. }
  82. int luat_i2s_setup(const luat_i2s_conf_t *conf) {
  83. if (I2s_tx_dma_init()){
  84. return -1;
  85. }
  86. memcpy(&i2s_conf, conf, sizeof(luat_i2s_conf_t));
  87. tls_i2s_io_init();
  88. // 然后转本地i2s配置
  89. I2S_InitDef opts = { I2S_MODE_MASTER, I2S_CTRL_STEREO, I2S_RIGHT_CHANNEL, I2S_Standard, I2S_DataFormat_16, 8000, 5000000 };
  90. opts.I2S_Mode_MS = conf->mode;
  91. opts.I2S_Mode_SS = conf->channel_format==LUAT_I2S_CHANNEL_STEREO?I2S_CTRL_STEREO:I2S_CTRL_MONO;
  92. opts.I2S_Mode_LR = conf->channel_format==0?I2S_LEFT_CHANNEL:I2S_RIGHT_CHANNEL;
  93. opts.I2S_Trans_STD = (conf->standard*0x1000000);
  94. opts.I2S_DataFormat = (conf->data_bits/8 - 1)*0x10;
  95. opts.I2S_AudioFreq = conf->sample_rate;
  96. // uint16_t fs = conf->data_bits * (conf->channel_format==LUAT_I2S_CHANNEL_STEREO?2:1) * conf->channel_bits/16;
  97. // printf("------------fs:%d\n", fs);
  98. opts.I2S_MclkFreq = 2*256*conf->sample_rate;
  99. wm_i2s_port_init(&opts);
  100. // wm_i2s_register_callback(NULL);
  101. i2s_conf.state = LUAT_I2S_STATE_STOP;
  102. return 0;
  103. }
  104. int luat_i2s_modify(uint8_t id,uint8_t channel_format,uint8_t data_bits,uint32_t sample_rate){
  105. if (id != 0) return -1;
  106. i2s_conf.channel_format = channel_format;
  107. i2s_conf.data_bits = data_bits;
  108. i2s_conf.sample_rate = sample_rate;
  109. wm_i2s_mono_select(channel_format==LUAT_I2S_CHANNEL_STEREO?I2S_CTRL_STEREO:I2S_CTRL_MONO);
  110. wm_i2s_left_channel_sel(channel_format==0?I2S_LEFT_CHANNEL:I2S_RIGHT_CHANNEL);
  111. wm_i2s_set_word_len((data_bits/8 - 1)*0x10);
  112. wm_i2s_set_freq(sample_rate, 2*256*sample_rate);
  113. return 0;
  114. }
  115. int luat_i2s_send(uint8_t id, uint8_t* buff, size_t len) {
  116. int ret;
  117. if (buff == NULL) {
  118. return -1;
  119. }
  120. if (len == 0) {
  121. return 0;
  122. }
  123. OS_BufferWrite(&dma_tx_buf, buff, len);
  124. if (i2s_conf.state == LUAT_I2S_STATE_STOP) {
  125. i2s_conf.state = LUAT_I2S_STATE_RUNING;
  126. ret = I2s_tx_send();
  127. if(ret == -1){
  128. LLOGE("fifo empty for send\n");
  129. i2s_conf.state = LUAT_I2S_STATE_STOP;
  130. return 0;
  131. }
  132. }
  133. return len;
  134. }
  135. int luat_i2s_recv(uint8_t id, uint8_t* buff, size_t len) {
  136. wm_i2s_rx_int((int16_t *)buff, len / 2);
  137. return len;
  138. }
  139. int luat_i2s_pause(uint8_t id) {
  140. wm_i2s_tx_enable(0);
  141. i2s_conf.state = LUAT_I2S_STATE_STOP;
  142. return 0;
  143. }
  144. int luat_i2s_resume(uint8_t id) {
  145. wm_i2s_tx_enable(1);
  146. return 0;
  147. }
  148. int luat_i2s_close(uint8_t id) {
  149. wm_i2s_tx_enable(0);
  150. i2s_conf.state = LUAT_I2S_STATE_STOP;
  151. if(dma_tx.channel){
  152. tls_dma_free(dma_tx.channel);
  153. }
  154. if (dma_tx_buf.Data){
  155. OS_DeInitBuffer(&dma_tx_buf);
  156. }
  157. return 0;
  158. }
  159. int luat_i2s_tx_stat(uint8_t id, size_t *buffsize, size_t* remain) {
  160. *buffsize = AUDIO_BUF_SIZE;
  161. *remain = dma_tx_buf.Pos;
  162. return 0;
  163. }