123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- #include "FreeRTOS.h"
- #include "chip.h"
- #include "audio.h"
- enum
- {
- REPLAY_EVT_NONE = 0x00,
- REPLAY_EVT_START = 0x01,
- REPLAY_EVT_STOP = 0x02,
- };
- struct audio_queue_data
- {
- uint8_t *data;
- int size;
- };
- struct audio_device *audio_dev[2] = {NULL, NULL};
- static int audio_send_replay_frame(struct audio_device *audio)
- {
- int result = 0;
- uint8_t *data;
- size_t dst_size, src_size;
- uint16_t position, remain_bytes = 0, index = 0;
- struct audio_buf_info *buf_info;
- struct audio_queue_data qdata;
- configASSERT(audio != NULL);
- buf_info = &audio->replay->buf_info;
- /* save current pos */
- position = audio->replay->pos;
- dst_size = buf_info->block_size;
- /* check replay queue is empty */
- if (xQueueIsQueueEmptyFromISR(audio->replay->queue) == pdTRUE)
- {
- /* ack stop event */
- if (audio->replay->event & REPLAY_EVT_STOP) {
- xQueueSendFromISR(audio->replay->cmp, NULL, 0);
- return 0;
- }
- /* send zero frames */
- memset(&buf_info->buffer[audio->replay->pos], 0, dst_size);
- audio->replay->pos += dst_size;
- audio->replay->pos %= buf_info->total_size;
- }
- else
- {
- memset(&buf_info->buffer[audio->replay->pos], 0, dst_size);
- /* copy data from memory pool to hardware device fifo */
- while (index < dst_size)
- {
- result = xQueuePeekFromISR(audio->replay->queue, &qdata);
- if (result != pdTRUE)
- {
- TRACE_DEBUG("under run %d, remain %d", audio->replay->pos, remain_bytes);
- audio->replay->pos -= remain_bytes;
- audio->replay->pos += dst_size;
- audio->replay->pos %= buf_info->total_size;
- audio->replay->read_index = 0;
- result = -1;
- break;
- }
-
- data = qdata.data;
- src_size = qdata.size;
- remain_bytes = configMIN((dst_size - index), (src_size - audio->replay->read_index));
- memcpy(&buf_info->buffer[audio->replay->pos],
- &data[audio->replay->read_index], remain_bytes);
- index += remain_bytes;
- audio->replay->read_index += remain_bytes;
- audio->replay->pos += remain_bytes;
- audio->replay->pos %= buf_info->total_size;
- if (audio->replay->read_index == src_size)
- {
- audio->replay->read_index = 0;
- xQueueReceiveFromISR(audio->replay->queue, &qdata, 0);
- for (int i = 0; i < AUDIO_REPLAY_MP_BLOCK_COUNT; i++) {
- if (qdata.data == audio->replay->mempool + AUDIO_REPLAY_MP_BLOCK_SIZE * i) {
- audio->replay->mpstatus[i] = 0;
- break;
- }
- }
- }
- }
- }
- if (audio->ops->transmit != NULL)
- {
- if (audio->ops->transmit(audio, &buf_info->buffer[position], NULL, dst_size) != dst_size)
- result = -1;
- }
- return result;
- }
- static int audio_flush_replay_frame(struct audio_device *audio)
- {
- int result = 0;
- if (audio->replay->write_index)
- {
- struct audio_queue_data qdata = {audio->replay->write_data, audio->replay->write_index};
- result = xQueueSend(audio->replay->queue, &qdata, portMAX_DELAY);
- audio->replay->write_index = 0;
- }
- return result;
- }
- static int audio_replay_start(struct audio_device *audio)
- {
- int result = 0;
- if (audio->replay->activated != true)
- {
- /* start playback hardware device */
- if (audio->ops->start)
- result = audio->ops->start(audio, AUDIO_STREAM_REPLAY);
- audio->replay->activated = true;
- TRACE_DEBUG("start audio replay device");
- }
- return result;
- }
- static int audio_replay_stop(struct audio_device *audio)
- {
- int result = 0;
- if (audio->replay->activated == true)
- {
- /* flush replay remian frames */
- audio_flush_replay_frame(audio);
- /* notify irq(or thread) to stop the data transmission */
- audio->replay->event |= REPLAY_EVT_STOP;
- /* waiting for the remaining data transfer to complete */
- xQueueReset(audio->replay->cmp);
- xQueueReceive(audio->replay->cmp, NULL, pdMS_TO_TICKS(1000));
- audio->replay->event &= ~REPLAY_EVT_STOP;
- /* stop playback hardware device */
- if (audio->ops->stop)
- result = audio->ops->stop(audio, AUDIO_STREAM_REPLAY);
- audio->replay->activated = false;
- TRACE_DEBUG("stop audio replay device");
- }
- return result;
- }
- static int audio_record_start(struct audio_device *audio)
- {
- int result = 0;
- if (audio->record->activated != true)
- {
- /* open audio record pipe */
- //device_open(RT_DEVICE(&audio->record->pipe), RT_DEVICE_OFLAG_RDONLY);
- /* start record hardware device */
- if (audio->ops->start)
- result = audio->ops->start(audio, AUDIO_STREAM_RECORD);
- audio->record->activated = true;
- TRACE_DEBUG("start audio record device");
- }
- return result;
- }
- static int audio_record_stop(struct audio_device *audio)
- {
- int result = 0;
- if (audio->record->activated == true)
- {
- /* stop record hardware device */
- if (audio->ops->stop)
- result = audio->ops->stop(audio, AUDIO_STREAM_RECORD);
- /* close audio record pipe */
- //device_close(RT_DEVICE(&audio->record->pipe));
- audio->record->activated = false;
- TRACE_DEBUG("stop audio record device");
- }
- return result;
- }
- static int audio_dev_init(struct audio_device *audio)
- {
- int result = 0;
- configASSERT(audio != NULL);
- /* initialize replay & record */
- audio->replay = NULL;
- audio->record = NULL;
- /* initialize replay */
- if (audio->flag == AUDIO_FLAG_REPLAY)
- {
- struct audio_replay *replay = (struct audio_replay *) pvPortMalloc(sizeof(struct audio_replay));
- if (replay == NULL)
- return -ENOMEM;
- memset(replay, 0, sizeof(struct audio_replay));
- /* alloc mempool */
- replay->mempool = pvPortMalloc(AUDIO_REPLAY_MP_BLOCK_SIZE * AUDIO_REPLAY_MP_BLOCK_COUNT);
- if (!replay->mempool)
- return -ENOMEM;
- /* init queue for audio replay */
- replay->queue = xQueueCreate(CFG_AUDIO_REPLAY_QUEUE_COUNT, sizeof(struct audio_queue_data));
- /* init mutex lock for audio replay */
- replay->lock = xSemaphoreCreateMutex();
- replay->cmp = xQueueCreate(1, 0);
- replay->activated = false;
- audio->replay = replay;
- }
- /* initialize record */
- else if (audio->flag == AUDIO_FLAG_RECORD)
- {
- struct audio_record *record = (struct audio_record *) pvPortMalloc(sizeof(struct audio_record));
- uint8_t *buffer;
- if (record == NULL)
- return -ENOMEM;
- memset(record, 0, sizeof(struct audio_record));
- /* init pipe for record*/
- buffer = pvPortMalloc(AUDIO_RECORD_PIPE_SIZE);
- if (buffer == NULL)
- {
- vPortFree(record);
- TRACE_ERROR("malloc memory for for record pipe failed");
- return -ENOMEM;
- }
- /* audio_pipe_init(&record->pipe, "record",
- (int32_t)(RT_PIPE_FLAG_FORCE_WR | RT_PIPE_FLAG_BLOCK_RD),
- buffer,
- RT_AUDIO_RECORD_PIPE_SIZE); */
- record->activated = false;
- audio->record = record;
- }
- /* initialize hardware configuration */
- if (audio->ops->init)
- audio->ops->init(audio);
- /* get replay buffer information */
- if (audio->ops->buffer_info)
- audio->ops->buffer_info(audio, &audio->replay->buf_info);
- return result;
- }
- struct audio_device *audio_dev_open(uint32_t oflag)
- {
- struct audio_device *audio = NULL;
- /* initialize the Rx/Tx structure according to open flag */
- if (oflag == AUDIO_FLAG_REPLAY)
- {
- audio = audio_dev[AUDIO_FLAG_REPLAY];
- if (audio && audio->replay->activated != true)
- {
- TRACE_DEBUG("open audio replay device, oflag = %x\n", oflag);
- audio->replay->write_index = 0;
- audio->replay->read_index = 0;
- audio->replay->pos = 0;
- audio->replay->event = REPLAY_EVT_NONE;
- for (int i = 0; i < AUDIO_REPLAY_MP_BLOCK_COUNT; i++)
- audio->replay->mpstatus[i] = 0;
- }
- }
- else if (oflag == AUDIO_FLAG_RECORD)
- {
- audio = audio_dev[AUDIO_FLAG_RECORD];
- /* open record pipe */
- if (audio && audio->record->activated != true)
- {
- TRACE_DEBUG("open audio record device ,oflag = %x\n", oflag);
- audio_record_start(audio);
- audio->record->activated = true;
- }
- }
- return audio;
- }
- int audio_dev_close(struct audio_device *audio)
- {
- configASSERT(audio != NULL);
- if (audio->flag == AUDIO_FLAG_REPLAY)
- {
- /* stop replay stream */
- audio_replay_stop(audio);
- }
- else if (audio->flag == AUDIO_FLAG_RECORD)
- {
- /* stop record stream */
- audio_record_stop(audio);
- }
- return 0;
- }
- size_t audio_dev_read(struct audio_device *audio, void *buffer, size_t size)
- {
- configASSERT(audio != NULL);
- if (!(audio->flag == AUDIO_FLAG_RECORD) || (audio->record == NULL))
- return 0;
- return 0;//device_read(RT_DEVICE(&audio->record->pipe), pos, buffer, size);
- }
- size_t audio_dev_write(struct audio_device *audio, const void *buffer, size_t size)
- {
- uint8_t *ptr;
- uint16_t block_size, remain_bytes, index = 0;
- configASSERT(audio != NULL);
- if (!(audio->flag == AUDIO_FLAG_REPLAY) || (audio->replay == NULL))
- return 0;
- /* push a new frame to replay data queue */
- ptr = (uint8_t *)buffer;
- block_size = AUDIO_REPLAY_MP_BLOCK_SIZE;
- xSemaphoreTake(audio->replay->lock, portMAX_DELAY);
- while (index < size)
- {
- /* request buffer from replay memory pool */
- if (audio->replay->write_index % block_size == 0)
- {
- uint8_t *mpbuf = NULL;
- uint32_t st = xTaskGetTickCount();
- while(1) {
- int i;
- portENTER_CRITICAL();
- for (i = 0; i < AUDIO_REPLAY_MP_BLOCK_COUNT; i++) {
- if (!audio->replay->mpstatus[i]) {
- mpbuf = audio->replay->mempool + AUDIO_REPLAY_MP_BLOCK_SIZE * i;
- audio->replay->mpstatus[i] = 1;
- break;
- }
- }
- portEXIT_CRITICAL();
- if (mpbuf)
- break;
- if (xTaskGetTickCount() - st > pdMS_TO_TICKS(1000)) {
- printf("wait mempool free timeout.\n");
- mpbuf = audio->replay->mempool;
- for (i = 1; i < AUDIO_REPLAY_MP_BLOCK_COUNT; i++)
- audio->replay->mpstatus[i] = 0;
- break;
- }
- vTaskDelay(1);
- }
- audio->replay->write_data = mpbuf;
- memset(audio->replay->write_data, 0, block_size);
- }
- /* copy data to replay memory pool */
- remain_bytes = configMIN((block_size - audio->replay->write_index), (size - index));
- memcpy(&audio->replay->write_data[audio->replay->write_index], &ptr[index], remain_bytes);
- index += remain_bytes;
- audio->replay->write_index += remain_bytes;
- audio->replay->write_index %= block_size;
- if (audio->replay->write_index == 0)
- {
- struct audio_queue_data qdata = {audio->replay->write_data, block_size};
- xQueueSend(audio->replay->queue, &qdata, portMAX_DELAY);
- }
- }
- xSemaphoreGive(audio->replay->lock);
- /* check replay state */
- if (audio->replay->activated != true)
- {
- audio_replay_start(audio);
- audio->replay->activated = true;
- }
- return index;
- }
- int audio_dev_configure(struct audio_device *audio, struct audio_caps *caps)
- {
- int result = 0;
- if (audio->ops->configure != NULL)
- {
- result = audio->ops->configure(audio, caps);
- }
- return result;
- }
- int audio_register(struct audio_device *audio, uint32_t flag, void *data)
- {
- int result = 0;
- configASSERT(audio != NULL);
- audio->rx_indicate = NULL;
- audio->tx_complete = NULL;
- audio->flag = flag;
- audio->user_data = data;
- /* initialize audio device */
- result = audio_dev_init(audio);
- if (flag == AUDIO_FLAG_REPLAY)
- audio_dev[AUDIO_FLAG_REPLAY] = audio;
- else if (flag == AUDIO_FLAG_RECORD)
- audio_dev[AUDIO_FLAG_RECORD] = audio;
- return result;
- }
- int audio_samplerate_to_speed(uint32_t bitValue)
- {
- int speed = 0;
- switch (bitValue)
- {
- case AUDIO_SAMP_RATE_8K:
- speed = 8000;
- break;
- case AUDIO_SAMP_RATE_11K:
- speed = 11052;
- break;
- case AUDIO_SAMP_RATE_16K:
- speed = 16000;
- break;
- case AUDIO_SAMP_RATE_22K:
- speed = 22050;
- break;
- case AUDIO_SAMP_RATE_32K:
- speed = 32000;
- break;
- case AUDIO_SAMP_RATE_44K:
- speed = 44100;
- break;
- case AUDIO_SAMP_RATE_48K:
- speed = 48000;
- break;
- case AUDIO_SAMP_RATE_96K:
- speed = 96000;
- break;
- case AUDIO_SAMP_RATE_128K:
- speed = 128000;
- break;
- case AUDIO_SAMP_RATE_160K:
- speed = 160000;
- break;
- case AUDIO_SAMP_RATE_172K:
- speed = 176400;
- break;
- case AUDIO_SAMP_RATE_192K:
- speed = 192000;
- break;
- default:
- break;
- }
- return speed;
- }
- void audio_tx_complete(struct audio_device *audio)
- {
- /* try to send next frame */
- audio_send_replay_frame(audio);
- }
- void audio_rx_done(struct audio_device *audio, uint8_t *pbuf, size_t len)
- {
- /* save data to record pipe */
- //device_write(RT_DEVICE(&audio->record->pipe), 0, pbuf, len);
- /* invoke callback */
- /* if (audio->parent.rx_indicate != NULL)
- audio->parent.rx_indicate(&audio->parent, len); */
- }
|