98 lines
2.7 KiB
C
98 lines
2.7 KiB
C
#include "audio_hal.h"
|
|
#include <string.h>
|
|
#include "main.h"
|
|
#include "elog.h"
|
|
#include "FreeRTOS.h"
|
|
#include "queue.h"
|
|
#include "heap.h"
|
|
|
|
static const char *TAG = "audio_hal";
|
|
|
|
typedef struct {
|
|
void *buffer_ptr;
|
|
uint32_t buffer_size;
|
|
} audio_sample_t;
|
|
|
|
static QueueHandle_t audio_queue = NULL;
|
|
static uint8_t *audio_buffer = NULL;
|
|
static uint32_t audio_buffer_length = 0;
|
|
|
|
void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
|
|
{
|
|
BaseType_t need_yield = pdFALSE;
|
|
audio_sample_t sample;
|
|
|
|
if (xQueueReceiveFromISR(audio_queue, &sample, &need_yield) == pdTRUE) {
|
|
memcpy(&audio_buffer[0], sample.buffer_ptr, sample.buffer_size); //复制到第一个缓冲区
|
|
free(sample.buffer_ptr); //释放使用完的缓冲区
|
|
}
|
|
|
|
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_SET);
|
|
portYIELD_FROM_ISR(need_yield);
|
|
}
|
|
|
|
void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
|
|
{
|
|
BaseType_t need_yield = pdFALSE;
|
|
audio_sample_t sample;
|
|
|
|
if (xQueueReceiveFromISR(audio_queue, &sample, &need_yield) == pdTRUE) {
|
|
memcpy(&audio_buffer[audio_buffer_length / 2], sample.buffer_ptr, sample.buffer_size); //复制到第二个缓冲区
|
|
free(sample.buffer_ptr); //释放使用完的缓冲区
|
|
}
|
|
|
|
HAL_GPIO_WritePin(LED_G_GPIO_Port, LED_G_Pin, GPIO_PIN_RESET);
|
|
portYIELD_FROM_ISR(need_yield);
|
|
}
|
|
|
|
void audio_hal_start(uint32_t sample_count, uint8_t sample_size)
|
|
{
|
|
audio_buffer_length = sample_count * sample_size * 2; //双缓冲
|
|
elog_info(TAG, "audio_hal_start: sample_count=%d, sample_size=%d, allocating %d bytes for audio buffer",
|
|
sample_count, sample_size, audio_buffer_length);
|
|
|
|
if (audio_buffer != NULL) {
|
|
elog_warn(TAG, "audio_hal_start: audio_buffer is not freed");
|
|
free_ahb(audio_buffer);
|
|
}
|
|
audio_buffer = malloc_ahb(audio_buffer_length);
|
|
memset(audio_buffer, 0, audio_buffer_length);
|
|
|
|
if (audio_queue != NULL) {
|
|
elog_warn(TAG, "audio_hal_start: audio_queue is not deleted");
|
|
vQueueDelete(audio_queue);
|
|
}
|
|
audio_queue = xQueueCreate(AUDIO_HAL_SAMPLE_QUEUE_SIZE, sizeof(audio_sample_t));
|
|
|
|
HAL_SAI_Transmit_DMA(&hsai_BlockB1, audio_buffer, sample_count * 2); //开始DMA循环发送
|
|
}
|
|
|
|
void audio_hal_stop(void)
|
|
{
|
|
HAL_SAI_DMAStop(&hsai_BlockB1);
|
|
|
|
vQueueDelete(audio_queue);
|
|
audio_queue = NULL;
|
|
|
|
free_ahb(audio_buffer);
|
|
audio_buffer = NULL;
|
|
}
|
|
|
|
void audio_hal_write(void *buffer_ptr, uint32_t buffer_size)
|
|
{
|
|
if (buffer_size == 0) {
|
|
return;
|
|
}
|
|
|
|
audio_sample_t sample = {
|
|
.buffer_ptr = buffer_ptr,
|
|
.buffer_size = buffer_size
|
|
};
|
|
|
|
if (uxQueueSpacesAvailable(audio_queue) == AUDIO_HAL_SAMPLE_QUEUE_SIZE) {
|
|
elog_warn(TAG, "audio_hal_write: queue is empty before xQueueSend");
|
|
}
|
|
|
|
xQueueSend(audio_queue, &sample, portMAX_DELAY); //发送缓冲区到队列中
|
|
}
|