#include "include.h" #include "driver_sddac.h" #include "usb_audio.h" #include "usb_com.h" #include "usb_audio_desc.h" #include "bsp_sddac.h" #include "utils_ring_buffer.h" #if USB_AUDIO_EN #define RING_BUF_LEN 0x480 uda_t uda_0 AT(.usb_buf.usb); typedef struct { ring_buffer_t ring_buf; s16 speed; } au_cbuf_cb_t; u8 usbmic_compli_xp_sys = 0; #if USB_MIC_EN AT(.usbdev.com.table) static const u8 mic_vol_tbl[3] = { 0x00,//min 0x00,//max 0x01,//res }; AT(.usbdev.com.table) static const u8 mic_vol_tbl1[3] = { 0xf9,//min 0x1e,//max 0x50,//res }; epcb_t epcb2_tx AT(.usb_buf.usb); u8 ep2_isoc_in[AUDIO_ISOIN_SIZE + 2]; u8 ude_micbuf[RING_BUF_LEN] AT(.usb_buf.aubuf.mic); au_cbuf_cb_t aumic_cb AT(.usb_buf.aubuf.mic); bool mic_is_start AT(.buf.uac.mic); uint8_t enc_buf[AUDIO_MIC_PACKET_SIZE] AT(.usb_buf.aubuf.mic); #if (AUDIO_DEC_ADPCM_EN) uint8_t pcm_data[ADPCM_BYTE_2_PCM16_BYTE(AUDIO_MIC_PACKET_SIZE)] AT(.usb_buf.aubuf.mic); #elif (AUDIO_DEC_MSBC_EN) uint8_t pcm_data[240] AT(.usb_buf.aubuf.mic); #elif (AUDIO_DEC_SBC_EN) uint8_t pcm_data[256] AT(.usb_buf.aubuf.mic); #else uint8_t pcm_data[256] AT(.usb_buf.aubuf.mic); #endif #endif //USB_MIC_EN #if USB_SPEAKER_EN AT(.usbdev.com.table) static const u8 spk_vol_tbl[3] = { 0x00,//min 0xff,//max 0x01,//res }; epcb_t epcb2_rx AT(.usb_buf.usb); u8 ep2_isoc_out[AUDIO_ISOOUT_SIZE + 4]; u8 ude_aubuf[AUDIO_ISOOUT_SIZE] AT(.usb_buf.aubuf.spk); u8 ude_speakerbuf[RING_BUF_LEN] AT(.usb_buf.aubuf.spk); au_cbuf_cb_t auspeaker_cb AT(.usb_buf.aubuf.spk); #endif void uda_run_loop_execute(void); #if USB_MIC_EN AT(.usbdev.com) void uda_set_isocin_flag(u8 val) { uda_t *uda = &uda_0; uda->flag_isocin_int = val; } AT(.usbdev.com) uint8_t uda_get_isocin_flag(void) { uda_t *uda = &uda_0; return uda->flag_isocin_int; } AT(.text.func.usbdev) void uda_mic_start_do(void) { /* Start mic */ printf("[UAC] mic start\n"); mic_is_start = true; //wireless_send_ctrl_cmd(WIRELESS_CTRL_CMD_CODE_MIC_ALLOW, 0, NULL); } AT(.text.func.usbdev) void uda_mic_stop_do(void) { /* Sotp mic */ printf("[UAC] mic stop\n"); mic_is_start = false; utils_ring_buffer_clear(&aumic_cb.ring_buf); //wireless_send_ctrl_cmd(WIRELESS_CTRL_CMD_CODE_MIC_DISALLOW, 0, NULL); } AT(.text.func.usbdev) bool uda_mic_check(void) { return mic_is_start; } void uda_mic_buffer_prepare(uint8_t *ibuf, uint32_t size) { if (size > sizeof(enc_buf)) { printf("ERR!!!\n"); sw_reset_kick(6); } memcpy(enc_buf, ibuf, size); } // API for upper layer AT(.usbdev.com) void usb_audio_mic_stream(void *ibuf, u32 sample) { if (ibuf == NULL) { #if (AUDIO_DEC_ADPCM_EN) adpcm_decode_block(pcm_data, enc_buf, sample); #elif (AUDIO_DEC_MSBC_EN || AUDIO_DEC_SBC_EN) sbc_decode_frame(enc_buf, AUDIO_MIC_PACKET_SIZE, pcm_data); #endif ibuf = pcm_data; } utils_ring_buffer_write(&aumic_cb.ring_buf, ibuf, (sample << 1)); } AT(.usbdev.com) static void uda_mic_stop(uda_t *uda) { printf("%s\n", __func__); uda_mic_stop_do(); uda->flag_isocin_en = 0; } AT(.usbdev.com) static void uda_mic_start(uda_t *uda) { printf("%s\n", __func__); uda->flag_isocin_en = 1; memset(uda->isoc_in->buf, 0, AUDIO_ISOIN_SIZE); if (usb_ep_transfer(uda->isoc_in)) { usb_ep_start_transfer(uda->isoc_in, AUDIO_ISOIN_SIZE); } memset(&aumic_cb, 0, sizeof(aumic_cb)); utils_ring_buffer_init(&aumic_cb.ring_buf, ude_micbuf, RING_BUF_LEN); #if (AUDIO_DEC_ADPCM_EN) adpcm_sample_idx_reset(); #elif (AUDIO_DEC_MSBC_EN) sbc_decode_init(1); #elif (AUDIO_DEC_SBC_EN) sbc_decode_init(0); //128 points #endif uda_mic_start_do(); } ///USB AUDIO iso in process(mic) AT(.usbdev.com) void ude_isoc_tx_process(void) { int mlen; au_cbuf_cb_t *s = &aumic_cb; uda_t *uda = &uda_0; u16 frame_size = AUDIO_ISOIN_SIZE; if (usb_ep_transfer(uda->isoc_in)) { mlen = frame_size + s->speed; if (!utils_ring_buffer_read(&s->ring_buf, uda->isoc_in->buf, mlen)) { memset(uda->isoc_in->buf, 0, mlen); } if (uda->mic_mute) { memset(uda->isoc_in->buf, 0, mlen); } usb_ep_start_transfer(uda->isoc_in, mlen); } } AT(.usbdev.com) bool uda_get_mic_mute(void) { u8 buf = uda_0.mic_mute; return usb_ep0_start_transfer(&buf, 1); } AT(.usbdev.com) void uda_set_mic_mute(u8 val) { uda_0.mic_mute = val; printf("mic set mute: %0d\n", val); } AT(.usbdev.com) void uda_set_mic_volume(u16 val) { printf("mic set volume: %04x\n", val); uda_0.mic_vol = val; } AT(.usbdev.com) bool uda_get_mic_volume(u8 req) { u8 buf[2] = {0}; u8 value; if(usbmic_compli_xp_sys) { uda_t *uda = &uda_0; if (req == UA_GET_CUR) { value = uda->mic_vol; } else { value = mic_vol_tbl[(req&0x7f) - 2]; } buf[0] = value; buf[1] = 0x00; if (req != UA_GET_RES) { value = mic_vol_tbl1[(req&0x7f) - 2]; buf[1] = value; } if (req == UA_GET_CUR) { buf[0] = 0x00; buf[1] = 0x09; } } else { uda_t *uda = &uda_0; if (req == UA_GET_CUR) { value = uda->mic_vol; printf("value4 = %02x\n",value); } else { value = mic_vol_tbl[(req&0x7f) - 2]; printf("value5 = %02x\n",value); } buf[0] = value; buf[1] = 0x00; if (req != UA_GET_RES) { buf[1] = 0x80; } } return usb_ep0_start_transfer(buf, 2); } #endif #if USB_SPEAKER_EN AT(.usbdev.com) void uda_set_isocout_flag(u8 val) { uda_t *uda = &uda_0; uda->flag_isocout_int = val; } AT(.usbdev.com) uint8_t uda_get_isocout_flag(void) { uda_t *uda = &uda_0; return uda->flag_isocout_int; } AT(.text.func.usbdev) void uda_speaker_start_do(void) { /* Start mic */ printf("[UAC] speaker start\n"); sddac_cmd(ENABLE); } AT(.text.func.usbdev) void uda_speaker_stop_do(void) { printf("[UAC] speaker stop\n"); sddac_cmd(DISABLE); } AT(.usbdev.com) static void uda_speaker_stop(uda_t *uda) { printf("%s\n", __func__); uda_speaker_stop_do(); uda->flag_isocout_en = 0; } AT(.usbdev.com) static void uda_speaker_start(uda_t *uda) { printf("%s\n", __func__); uda->flag_isocout_en = 1; memset(&auspeaker_cb, 0x00, sizeof(auspeaker_cb)); utils_ring_buffer_init(&auspeaker_cb.ring_buf, ude_speakerbuf, RING_BUF_LEN); uda_speaker_start_do(); } ///USB AUDIO iso out process(speaker) AT(.usbdev.com) void ude_isoc_rx_process(void) { uda_t *uda = &uda_0; u8 *aubuf = ude_aubuf; if (uda->spk_mute) { memset(aubuf, 0, AUDIO_ISOOUT_SIZE); } else { memcpy(aubuf, ep2_isoc_out, AUDIO_ISOOUT_SIZE); } usb_ep_clear_rx_fifo(uda->isoc_out); utils_ring_buffer_write(&auspeaker_cb.ring_buf, aubuf, AUDIO_ISOOUT_SIZE); } AT(.usbdev.com) bool uda_get_spk_volume(u8 req) { u8 buf[2]={0}; u8 value; uda_t *uda = &uda_0; if (req == UA_GET_CUR) { value = uda->spk_vol; } else { value = spk_vol_tbl[(req&0x7f) - 2]; } buf[0] = value; buf[1] = 0x00; if (req != UA_GET_RES) { buf[1] = 0x80; } return usb_ep0_start_transfer(&buf, 2); } AT(.usbdev.com) void uda_set_spk_mute(u8 val) { uda_0.spk_mute = val; printf("spk set mute: %d\n", val); } AT(.usbdev.com) void uda_set_spk_volume(u16 val) { printf("spk set volume: %04x\n", val); uda_0.spk_vol = (u8)val; } AT(.usbdev.com) void uda_speaker_sync(void) { au_cbuf_cb_t *s = &auspeaker_cb; switch(s->speed) { case -2: if(s->ring_buf.data_len >= 1152) { s->speed = 0; } break; case 0: if(s->ring_buf.data_len >= 1152) { s->speed = 2; } else if(s->ring_buf.data_len < 384) { s->speed = -2; } break; case 2: if(s->ring_buf.data_len < 1152) { s->speed = 0; } break; } } AT(.usbdev.com) bool uda_get_spk_mute(void) { u8 buf = uda_0.spk_mute; return usb_ep0_start_transfer(&buf, 1); } // API for upper layer AT(.com_text.usbdev) void usb_audio_speaker_stream(void *obuf, u32 *sample) { au_cbuf_cb_t *s = &auspeaker_cb; int mlen; mlen = AUDIO_ISOOUT_SIZE + s->speed; if (!utils_ring_buffer_read(&s->ring_buf, obuf, mlen)) { memset(obuf, 0x00, mlen); } *sample = mlen >> 1; } #endif void usb_audio_process(void) { uda_run_loop_execute(); } ///USB AUDIO endpoint reset AT(.usbdev.com) void usb_isoc_ep_reset(void) { uda_t *uda = &uda_0; #if USB_MIC_EN if (uda->isoc_in->index) { usb_ep_reset(uda->isoc_in); } #endif // USB_MIC_EN #if USB_SPEAKER_EN if (uda->isoc_out->index) { usb_ep_reset(uda->isoc_out); } #endif // USB_SPEAKER_EN } AT(.usbdev.com) void uda_run_loop_execute(void) { uda_t *uda = &uda_0; #if USB_MIC_EN if (uda->flag_isocin_en != uda->flag_isocin_int) { if (uda->flag_isocin_int) { delay_5ms(2); //delay 10ms启动MIC, 等待SET CUR命令先处理(例如设采样率) uda_mic_start(uda); } else { uda_mic_stop(uda); } } #endif // USB_MIC_EN #if USB_SPEAKER_EN if (uda->flag_isocout_en != uda->flag_isocout_int) { if (uda->flag_isocout_int) { uda_speaker_start(uda); } else { uda_speaker_stop(uda); } } #endif // USB_MIC_EN } void uda_exit(uda_t *uda) { #if USB_MIC_EN if (uda->flag_isocin_en) { uda_mic_stop(uda); } #endif } void uda_init(void ) { epcb_t *epcb; memset(&uda_0, 0, sizeof(uda_t)); uda_t *uda = &uda_0; #if USB_MIC_EN uda_0.isoc_in = &epcb2_tx; memset(uda->isoc_in, 0x00, sizeof(epcb_t)); usb_ep_callback_register(ude_isoc_tx_process, USB_AUDIO_EP_IN_INDEX, EP_DIR_IN); //usb audio mic ep init memset(ep2_isoc_in, 0, sizeof(ep2_isoc_in)); epcb = uda->isoc_in; epcb->dir = EP_DIR_IN; epcb->index = USB_AUDIO_EP_IN_INDEX; epcb->type = EP_TYPE_ISOC; epcb->epsize = AUDIO_ISOIN_SIZE; epcb->buf = ep2_isoc_in; epcb->first_pkt = 0; epcb->xlen = 0; usb_ep_init(epcb); uda->mic_vol = 0x6a; //min:0x00, max:0xff uda->mic_mute = 0; uda->flag_isocin_int = 0; uda->flag_isocin_en = 0; #endif #if USB_SPEAKER_EN uda_0.isoc_out = &epcb2_rx; memset(uda->isoc_out, 0x00, sizeof(epcb_t)); usb_ep_callback_register(ude_isoc_rx_process, USB_AUDIO_EP_OUT_INDEX, EP_DIR_OUT); //usb audio speaker ep init memset(ep2_isoc_out, 0, sizeof(ep2_isoc_out)); epcb = uda->isoc_out; epcb->dir = EP_DIR_OUT; epcb->index = USB_AUDIO_EP_OUT_INDEX; epcb->type = EP_TYPE_ISOC; epcb->epsize = AUDIO_ISOOUT_SIZE; epcb->buf = ep2_isoc_out; usb_ep_init(epcb); uda->spk_vol = 0x80; //min:0x00, max:0xff uda->spk_mute = 0; uda->flag_isocout_int = 0; uda->flag_isocout_en = 0; #endif printf("uda_init success\n"); } void usb_audio_init(void) { /* Add application layer initialize if need */ } void usb_audio_deinit(void) { uda_t *uda = &uda_0; uda_exit(uda); } #endif