lock_lfvx/bk_idk/middleware/driver/audio/audio_ring_buff.c
2025-10-10 16:07:00 +08:00

259 lines
7.9 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <driver/dma.h>
#include <bk_general_dma.h>
#include <driver/audio_ring_buff.h>
#include <stdlib.h>
#include <string.h>
//#define RWP_SAFE_INTERVAL (4)
#define RWP_SAFE_INTERVAL (0)
void ring_buffer_init(RingBufferContext* rb, uint8_t* addr, uint32_t capacity, dma_id_t dma_id, uint32_t dma_type)
{
rb->address = addr;
rb->capacity = capacity;
rb->wp = 0;
rb->rp = 0;
rb->dma_id = dma_id;
rb->dma_type = dma_type;
if(dma_id != DMA_ID_MAX)
{
if(rb->dma_type == RB_DMA_TYPE_READ)
{
//dma_channel_src_curr_address_set(dma, (uint32_t)addr);
dma_set_src_pause_addr(dma_id, (uint32_t)addr);
}
else if(rb->dma_type == RB_DMA_TYPE_WRITE)
{
//dma_channel_dst_curr_address_set(dma, (uint32_t)addr + capacity);
dma_set_dst_pause_addr(dma_id, (uint32_t)addr + capacity);
}
}
}
void ring_buffer_clear(RingBufferContext* rb)
{
rb->wp = 0;
rb->rp = 0;
if(rb->dma_id != DMA_ID_MAX)
{
if(rb->dma_type == RB_DMA_TYPE_READ)
{
//ring buffer数据都清空了所以设置读暂停的地址为ring buffer起始地址,上来就暂停
//dma_channel_src_curr_address_set(rb->dma, (uint32_t)rb->address);
dma_set_src_pause_addr(rb->dma_id, (uint32_t)rb->address);
}
else if(rb->dma_type == RB_DMA_TYPE_WRITE)
{
//ring buffer数据都清空了所以设置写暂停的地址为ring buffer结束地址,上来可以写满ring buffer
//dma_channel_dst_curr_address_set(rb->dma, (uint32_t)rb->address + rb->capacity);
dma_set_dst_pause_addr(rb->dma_id, (uint32_t)rb->address + rb->capacity);
}
}
}
uint32_t ring_buffer_read(RingBufferContext* rb, uint8_t* buffer, uint32_t size)
{
uint32_t required_bytes = size;
uint32_t read_bytes;
uint32_t remain_bytes;
uint32_t wp;
if((rb->dma_id != DMA_ID_MAX) && (rb->dma_type == RB_DMA_TYPE_WRITE))
{
//读取DMA寄存器[dma1_dest_wr_addr],获取此时已经读到的地址
//wp = rb->wp = dma_channel_is_enabled(rb->dma) ? dma_channel_dst_curr_pointer_get(rb->dma) - (uint32_t)rb->address : 0;
wp = rb->wp = bk_dma_get_enable_status(rb->dma_id) ? dma_get_dest_write_addr(rb->dma_id) - (uint32_t)rb->address : 0;
}
else
{
wp = rb->wp;
}
if(required_bytes == 0) return 0;
if(wp >= rb->rp)
{
remain_bytes = wp - rb->rp;
if(required_bytes > remain_bytes)
{
read_bytes = remain_bytes;
memcpy(buffer, &rb->address[rb->rp], read_bytes);
//rb->rp += read_bytes;
rb->rp = (rb->rp + read_bytes) % rb->capacity;
}
else
{
read_bytes = required_bytes;
memcpy(buffer, &rb->address[rb->rp], read_bytes);
//rb->rp += read_bytes;
rb->rp = (rb->rp + read_bytes) % rb->capacity;
}
}
else
{
remain_bytes = rb->capacity - rb->rp;
if(required_bytes > remain_bytes)
{
read_bytes = remain_bytes;
memcpy(buffer, &rb->address[rb->rp], read_bytes);
if(required_bytes - read_bytes > wp)
{
memcpy(buffer + read_bytes, &rb->address[0], wp);
rb->rp = wp;
read_bytes += wp;
}
else
{
memcpy(buffer + read_bytes, &rb->address[0], required_bytes - read_bytes);
rb->rp = required_bytes - read_bytes;
read_bytes = required_bytes;
}
}
else
{
read_bytes = required_bytes;
memcpy(buffer, &rb->address[rb->rp], read_bytes);
//rb->rp += read_bytes;
rb->rp = (rb->rp + read_bytes) % rb->capacity;
}
}
#if 0
if(rb->dma && rb->dma_type == RB_DMA_TYPE_WRITE)
{
dma_channel_dst_curr_address_set(rb->dma, (uint32_t)&rb->address[rb->rp]);
}
#endif
return read_bytes;
}
uint32_t ring_buffer_write(RingBufferContext* rb, uint8_t* buffer, uint32_t size)
{
uint32_t remain_bytes;
uint32_t write_bytes = size;
uint32_t rp;
if(write_bytes == 0) return 0;
if((rb->dma_id != DMA_ID_MAX) && (rb->dma_type == RB_DMA_TYPE_READ))
{
//读取DMA寄存器[dma0_src_rd_addr],获取此时已经读到的地址
//rp = rb->rp = dma_channel_is_enabled(rb->dma) ? dma_channel_src_curr_pointer_get(rb->dma) - (uint32_t)rb->address : 0;
rp = rb->rp = bk_dma_get_enable_status(rb->dma_id) ? dma_get_src_read_addr(rb->dma_id) - (uint32_t)rb->address : 0;
}
else
{
rp = rb->rp;
}
if(rb->wp >= rp)
{
remain_bytes = rb->capacity - rb->wp + rp;
if(remain_bytes >= write_bytes + RWP_SAFE_INTERVAL)
{
remain_bytes = rb->capacity - rb->wp;
if(remain_bytes >= write_bytes)
{
memcpy(&rb->address[rb->wp], buffer, write_bytes);
//rb->wp += write_bytes;
rb->wp = (rb->wp + write_bytes) % rb->capacity;
}
else
{
memcpy(&rb->address[rb->wp], buffer, remain_bytes);
rb->wp = write_bytes - remain_bytes;
memcpy(&rb->address[0], &buffer[remain_bytes], rb->wp);
}
}
else
{
return 0;
}
}
else
{
remain_bytes = rp - rb->wp;
if(remain_bytes >= write_bytes + RWP_SAFE_INTERVAL)
{
memcpy(&rb->address[rb->wp], buffer, write_bytes);
//rb->wp += write_bytes;
rb->wp = (rb->wp + write_bytes) % rb->capacity;
}
else
{
return 0;
}
}
if(rb->wp >= rb->capacity && rb->rp)
{
rb->wp = 0;
}
if((rb->dma_id != DMA_ID_MAX) && (rb->dma_type == RB_DMA_TYPE_READ))
{
//dma_channel_src_curr_address_set(rb->dma, (uint32_t)&rb->address[rb->wp]); //作用是啥?
//向dma读取的ring buffer写数据写入一段数据后需要将“写指针wp”指向的地址值写入[dma0_src_pause_addr]
//这样可以确保DMA读取到该地址时暂停搬运
dma_set_src_pause_addr(rb->dma_id, (uint32_t)&rb->address[rb->wp]);
}
return write_bytes;
}
uint32_t ring_buffer_get_fill_size(RingBufferContext* rb)
{
uint32_t rp, wp;
uint32_t fill_size;
if(rb->dma_id != DMA_ID_MAX)
{
if(rb->dma_type == RB_DMA_TYPE_READ)
{
//rp = rb->rp = dma_channel_is_enabled(rb->dma) ? dma_channel_src_curr_pointer_get(rb->dma) - (uint32_t)rb->address : 0;
rp = rb->rp = bk_dma_get_enable_status(rb->dma_id) ? dma_get_src_read_addr(rb->dma_id) - (uint32_t)rb->address : 0;
wp = rb->wp;
}
else if(rb->dma_type == RB_DMA_TYPE_WRITE)
{
rp = rb->rp;
//wp = rb->wp = dma_channel_is_enabled(rb->dma) ? dma_channel_dst_curr_pointer_get(rb->dma) - (uint32_t)rb->address : 0;
wp = rb->wp = bk_dma_get_enable_status(rb->dma_id) ? dma_get_dest_write_addr(rb->dma_id) - (uint32_t)rb->address : 0;
}
else
{
rp = rb->rp;
wp = rb->wp;
}
}
else
{
rp = rb->rp;
wp = rb->wp;
}
fill_size = wp >= rp ? wp - rp : rb->capacity - rp + wp;
return fill_size;
}
uint32_t ring_buffer_get_free_size(RingBufferContext* rb)
{
uint32_t free_size;
free_size = rb->capacity - ring_buffer_get_fill_size(rb);
return free_size > RWP_SAFE_INTERVAL ? free_size - RWP_SAFE_INTERVAL : 0;
}