Files
QD4C-firmware/libraries/zf_common/zf_common_fifo.c
2023-12-11 21:45:06 +08:00

555 lines
22 KiB
C
Raw Permalink 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.

/*********************************************************************************************************************
* CH32V307VCT6 Opensourec Library 即CH32V307VCT6 开源库)是一个基于官方 SDK 接口的第三方开源库
* Copyright (c) 2022 SEEKFREE 逐飞科技
*
* 本文件是CH32V307VCT6 开源库的一部分
*
* CH32V307VCT6 开源库 是免费软件
* 您可以根据自由软件基金会发布的 GPLGNU General Public License即 GNU通用公共许可证的条款
* 即 GPL 的第3版即 GPL3.0)或(您选择的)任何后来的版本,重新发布和/或修改它
*
* 本开源库的发布是希望它能发挥作用,但并未对其作任何的保证
* 甚至没有隐含的适销性或适合特定用途的保证
* 更多细节请参见 GPL
*
* 您应该在收到本开源库的同时收到一份 GPL 的副本
* 如果没有,请参阅<https://www.gnu.org/licenses/>
*
* 额外注明:
* 本开源库使用 GPL3.0 开源许可证协议 以上许可申明为译文版本
* 许可申明英文版在 libraries/doc 文件夹下的 GPL3_permission_statement.txt 文件中
* 许可证副本在 libraries 文件夹下 即该文件夹下的 LICENSE 文件
* 欢迎各位使用并传播本程序 但修改内容时必须保留逐飞科技的版权声明(即本声明)
*
* 文件名称 zf_common_fifo
* 公司名称 成都逐飞科技有限公司
* 版本信息 查看 libraries/doc 文件夹内 version 文件 版本说明
* 开发环境 MounRiver Studio V1.8.1
* 适用平台 CH32V307VCT6
* 店铺链接 https://seekfree.taobao.com/
*
* 修改记录
* 日期 作者 备注
* 2022-09-15 大W first version
********************************************************************************************************************/
#include "zf_common_debug.h"
#include "zf_common_fifo.h"
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 FIFO 头指针位移
// 参数说明 *fifo FIFO 对象指针
// 参数说明 offset 偏移量
// 返回参数 void
// 使用示例 fifo_head_offset(fifo, 1);
// 备注信息 本函数在文件内部调用 用户不用关注 也不可修改
//-------------------------------------------------------------------------------------------------------------------
static void fifo_head_offset (fifo_struct *fifo, uint32 offset)
{
fifo->head += offset;
while(fifo->max <= fifo->head) // 如果范围超过则减缓冲区大小 直到小于最大缓冲区大小
{
fifo->head -= fifo->max;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 FIFO 尾指针位移
// 参数说明 *fifo FIFO 对象指针
// 参数说明 offset 偏移量
// 返回参数 void
// 使用示例 fifo_end_offset(fifo, 1);
// 备注信息 本函数在文件内部调用 用户不用关注 也不可修改
//-------------------------------------------------------------------------------------------------------------------
static void fifo_end_offset (fifo_struct *fifo, uint32 offset)
{
fifo->end += offset;
while(fifo->max <= fifo->end) // 如果范围超过则减缓冲区大小 直到小于最大缓冲区大小
{
fifo->end -= fifo->max;
}
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 FIFO 重置缓冲器
// 参数说明 *fifo FIFO 对象指针
// 返回参数 void
// 使用示例 fifo_clear(fifo);
// 备注信息 清空当前 FIFO 对象的内存
//-------------------------------------------------------------------------------------------------------------------
fifo_state_enum fifo_clear (fifo_struct *fifo)
{
zf_assert(fifo != NULL);
fifo_state_enum return_state = FIFO_SUCCESS;
do
{
if(FIFO_CLEAR & fifo->execution)
{
return_state = FIFO_CLEAR_UNDO;
break;
}
fifo->execution |= FIFO_CLEAR;
fifo->head = 0;
fifo->end = 0;
fifo->size = fifo->max;
switch(fifo->type)
{
case FIFO_DATA_8BIT:
memset(fifo->buffer, 0, fifo->max);
break;
case FIFO_DATA_16BIT:
memset(fifo->buffer, 0, fifo->max * 2);
break;
case FIFO_DATA_32BIT:
memset(fifo->buffer, 0, fifo->max * 4);
break;
}
// memset(fifo->buffer, 0, fifo->max);
fifo->execution &= ~FIFO_CLEAR;
}while(0);
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 FIFO 查询当前数据个数
// 参数说明 *fifo FIFO 对象指针
// 返回参数 uint32 已使用长度
// 使用示例 uint32 len = fifo_used(fifo);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
uint32 fifo_used (fifo_struct *fifo)
{
zf_assert(fifo != NULL);
return (fifo->max - fifo->size);
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 向 FIFO 中写入数据
// 参数说明 *fifo FIFO 对象指针
// 参数说明 dat 数据
// 返回参数 fifo_state_enum 操作状态
// 使用示例 zf_log(fifo_write_element(&fifo, data) == FIFO_SUCCESS, "fifo_write_byte error");
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
fifo_state_enum fifo_write_element (fifo_struct *fifo, uint32 dat)
{
zf_assert(fifo != NULL);
fifo_state_enum return_state = FIFO_SUCCESS;
do
{
if(FIFO_WRITE & fifo->execution)
{
return_state = FIFO_WRITE_UNDO;
break;
}
fifo->execution |= FIFO_WRITE;
if(1 <= fifo->size) // 剩余空间足够装下本次数据
{
switch(fifo->type)
{
case FIFO_DATA_8BIT:
((uint8 *)fifo->buffer)[fifo->head] = dat;
break;
case FIFO_DATA_16BIT:
((uint16 *)fifo->buffer)[fifo->head] = dat;
break;
case FIFO_DATA_32BIT:
((uint32 *)fifo->buffer)[fifo->head] = dat;
break;
}
fifo_head_offset(fifo, 1); // 头指针偏移
fifo->size -= 1; // 缓冲区剩余长度减小
}
else
{
return_state = FIFO_SPACE_NO_ENOUGH;
}
fifo->execution &= ~FIFO_WRITE;
}while(0);
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 向 FIFO 中写入数据
// 参数说明 *fifo FIFO 对象指针
// 参数说明 *dat 数据来源缓冲区指针
// 参数说明 length 需要写入的数据长度
// 返回参数 fifo_state_enum 操作状态
// 使用示例 zf_log(fifo_write_buffer(&fifo, data, 32) == FIFO_SUCCESS, "fifo_write_buffer error");
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
fifo_state_enum fifo_write_buffer (fifo_struct *fifo, void *dat, uint32 length)
{
zf_assert(fifo != NULL);
fifo_state_enum return_state = FIFO_SUCCESS;
uint32 temp_length = 0;
do
{
if(NULL == dat)
{
return_state = FIFO_BUFFER_NULL;
break;
}
if(FIFO_WRITE & fifo->execution)
{
return_state = FIFO_WRITE_UNDO;
break;
}
fifo->execution |= FIFO_WRITE;
if(length <= fifo->size) // 剩余空间足够装下本次数据
{
temp_length = fifo->max - fifo->head; // 计算头指针距离缓冲区尾还有多少空间
if(length > temp_length) // 距离缓冲区尾长度不足写入数据 环形缓冲区分段操作
{
switch(fifo->type)
{
case FIFO_DATA_8BIT:
memcpy(
&(((uint8 *)fifo->buffer)[fifo->head]),
dat, temp_length); // 拷贝第一段数据
fifo_head_offset(fifo, temp_length); // 头指针偏移
memcpy(
&(((uint8 *)fifo->buffer)[fifo->head]),
&(((uint8 *)dat)[temp_length]),
length - temp_length); // 拷贝第二段数据
fifo_head_offset(fifo, length - temp_length); // 头指针偏移
break;
case FIFO_DATA_16BIT:
memcpy(
&(((uint16 *)fifo->buffer)[fifo->head]),
dat, temp_length * 2); // 拷贝第一段数据
fifo_head_offset(fifo, temp_length); // 头指针偏移
memcpy(
&(((uint16 *)fifo->buffer)[fifo->head]),
&(((uint16 *)dat)[temp_length]),
(length - temp_length) * 2); // 拷贝第二段数据
fifo_head_offset(fifo, length - temp_length); // 头指针偏移
break;
case FIFO_DATA_32BIT:
memcpy(
&(((uint32 *)fifo->buffer)[fifo->head]),
dat, temp_length * 4); // 拷贝第一段数据
fifo_head_offset(fifo, temp_length); // 头指针偏移
memcpy(
&(((uint32 *)fifo->buffer)[fifo->head]),
&(((uint32 *)dat)[temp_length]),
(length - temp_length) * 4); // 拷贝第二段数据
fifo_head_offset(fifo, length - temp_length); // 头指针偏移
break;
}
}
else
{
switch(fifo->type)
{
case FIFO_DATA_8BIT:
memcpy(
&(((uint8 *)fifo->buffer)[fifo->head]),
dat, length); // 一次完整写入
fifo_head_offset(fifo, length); // 头指针偏移
break;
case FIFO_DATA_16BIT:
memcpy(
&(((uint16 *)fifo->buffer)[fifo->head]),
dat, length * 2); // 一次完整写入
fifo_head_offset(fifo, length); // 头指针偏移
break;
case FIFO_DATA_32BIT:
memcpy(
&(((uint32 *)fifo->buffer)[fifo->head]),
dat, length * 4); // 一次完整写入
fifo_head_offset(fifo, length); // 头指针偏移
break;
}
// memcpy(&fifo->buffer[fifo->head], dat, length); // 一次完整写入
// fifo_head_offset(fifo, length); // 头指针偏移
}
fifo->size -= length; // 缓冲区剩余长度减小
}
else
{
return_state = FIFO_SPACE_NO_ENOUGH;
}
fifo->execution &= ~FIFO_WRITE;
}while(0);
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 从 FIFO 读取数据
// 参数说明 *fifo FIFO 对象指针
// 参数说明 *dat 目标缓冲区指针
// 参数说明 flag 是否变更 FIFO 状态 可选择是否清空读取的数据
// 返回参数 fifo_state_enum 操作状态
// 使用示例 zf_log(fifo_read_element(&fifo, data, FIFO_READ_ONLY) == FIFO_SUCCESS, "fifo_read_byte error");
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
fifo_state_enum fifo_read_element (fifo_struct *fifo, void *dat, fifo_operation_enum flag)
{
zf_assert(fifo != NULL);
fifo_state_enum return_state = FIFO_SUCCESS;
do
{
if(NULL == dat)
{
return_state = FIFO_BUFFER_NULL;
break;
}
fifo->execution |= FIFO_READ;
if(1 > fifo_used(fifo))
{
return_state = FIFO_DATA_NO_ENOUGH; // 标志数据不够
}
switch(fifo->type)
{
case FIFO_DATA_8BIT:
*((uint8 *)dat) = ((uint8 *)fifo->buffer)[fifo->end];
break;
case FIFO_DATA_16BIT:
*((uint16 *)dat) = ((uint16 *)fifo->buffer)[fifo->end];
break;
case FIFO_DATA_32BIT:
*((uint32 *)dat) = ((uint32 *)fifo->buffer)[fifo->end];
break;
}
if(flag == FIFO_READ_AND_CLEAN) // 如果选择读取并更改 FIFO 状态
{
if(FIFO_CLEAR & fifo->execution)
{
return_state = FIFO_CLEAR_UNDO;
break;
}
fifo->execution |= FIFO_CLEAR;
fifo_end_offset(fifo, 1); // 移动 FIFO 头指针
fifo->size += 1;
fifo->execution &= ~FIFO_CLEAR;
}
}while(0);
fifo->execution &= FIFO_READ;
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 从 FIFO 读取数据
// 参数说明 *fifo FIFO 对象指针
// 参数说明 *dat 目标缓冲区指针
// 参数说明 *length 读取的数据长度 如果没有这么多数据这里会被修改
// 参数说明 flag 是否变更 FIFO 状态 可选择是否清空读取的数据
// 返回参数 fifo_state_enum 操作状态
// 使用示例 zf_log(fifo_read_buffer(&fifo, data, &length, FIFO_READ_ONLY) == FIFO_SUCCESS, "fifo_read_buffer error");
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
fifo_state_enum fifo_read_buffer (fifo_struct *fifo, void *dat, uint32 *length, fifo_operation_enum flag)
{
zf_assert(fifo != NULL);
zf_assert(length != NULL);
fifo_state_enum return_state = FIFO_SUCCESS;
uint32 temp_length;
uint32 fifo_data_length;
do
{
if(NULL == dat)
{
return_state = FIFO_BUFFER_NULL;
break;
}
fifo->execution |= FIFO_READ;
fifo_data_length = fifo_used(fifo);
if(*length > fifo_data_length)
{
*length = fifo_data_length; // 纠正读取的长度
return_state = FIFO_DATA_NO_ENOUGH; // 标志数据不够
}
temp_length = fifo->max - fifo->end; // 计算尾指针距离缓冲区尾还有多少空间
if(*length <= temp_length) // 足够一次性读取完毕
{
switch(fifo->type)
{
case FIFO_DATA_8BIT:
memcpy(dat, &(((uint8 *)fifo->buffer)[fifo->end]), *length);
break;
case FIFO_DATA_16BIT:
memcpy(dat, &(((uint16 *)fifo->buffer)[fifo->end]), *length * 2);
break;
case FIFO_DATA_32BIT:
memcpy(dat, &(((uint32 *)fifo->buffer)[fifo->end]), *length * 4);
break;
}
}
else
{
switch(fifo->type)
{
case FIFO_DATA_8BIT:
memcpy(dat, &(((uint8 *)fifo->buffer)[fifo->end]), temp_length);
memcpy(&(((uint8 *)dat)[temp_length]), fifo->buffer, *length - temp_length);
break;
case FIFO_DATA_16BIT:
memcpy(dat, &(((uint16 *)fifo->buffer)[fifo->end]), temp_length * 2);
memcpy(&(((uint16 *)dat)[temp_length]), fifo->buffer, (*length - temp_length) * 2);
break;
case FIFO_DATA_32BIT:
memcpy(dat, &(((uint32 *)fifo->buffer)[fifo->end]), temp_length * 4);
memcpy(&(((uint32 *)dat)[temp_length]), fifo->buffer, (*length - temp_length) * 4);
break;
}
}
if(flag == FIFO_READ_AND_CLEAN) // 如果选择读取并更改 FIFO 状态
{
if(FIFO_CLEAR & fifo->execution)
{
return_state = FIFO_CLEAR_UNDO;
break;
}
fifo->execution |= FIFO_CLEAR;
fifo_end_offset(fifo, *length); // 移动 FIFO 头指针
fifo->size += *length;
fifo->execution &= ~FIFO_CLEAR;
}
}while(0);
fifo->execution &= FIFO_READ;
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 从 FIFO 尾部读取指定长度 buffer
// 参数说明 *fifo FIFO 对象指针
// 参数说明 *dat 目标缓冲区指针
// 参数说明 *length 读取的数据长度 如果没有这么多数据这里会被修改
// 参数说明 flag 是否变更 FIFO 状态 可选择是否清空读取的数据
// 返回参数 fifo_state_enum 操作状态
// 使用示例 zf_log(fifo_read_tail_buffer(&fifo, data, &length, FIFO_READ_ONLY) == FIFO_SUCCESS, "fifo_read_buffer error");
// 备注信息 如果使用 FIFO_READ_AND_CLEAN 操作 将会丢弃所有数据并清空整个 FIFO
// 如果使用 FIFO_READ_AND_CLEAN 操作 将会丢弃所有数据并清空整个 FIFO
// 如果使用 FIFO_READ_AND_CLEAN 操作 将会丢弃所有数据并清空整个 FIFO
//-------------------------------------------------------------------------------------------------------------------
fifo_state_enum fifo_read_tail_buffer (fifo_struct *fifo, void *dat, uint32 *length, fifo_operation_enum flag)
{
zf_assert(fifo != NULL);
zf_assert(length != NULL);
fifo_state_enum return_state = FIFO_SUCCESS;
uint32 temp_length;
uint32 fifo_data_length;
do
{
if(NULL == dat)
{
return_state = FIFO_BUFFER_NULL;
break;
}
fifo->execution |= FIFO_READ;
fifo_data_length = fifo_used(fifo);
if(*length > fifo_data_length)
{
*length = fifo_data_length; // 纠正读取的长度
return_state = FIFO_DATA_NO_ENOUGH; // 标志数据不够
}
if((fifo->head > fifo->end) || (fifo->head >= *length))
{
switch(fifo->type)
{
case FIFO_DATA_8BIT:
memcpy(dat, &(((uint8 *)fifo->buffer)[fifo->head - *length]), *length);
break;
case FIFO_DATA_16BIT:
memcpy(dat, &(((uint16 *)fifo->buffer)[fifo->head - *length]), *length * 2);
break;
case FIFO_DATA_32BIT:
memcpy(dat, &(((uint32 *)fifo->buffer)[fifo->head - *length]), *length * 4);
break;
}
}
else
{
temp_length = *length - fifo->head; // 计算尾指针距离缓冲区尾还有多少空间
switch(fifo->type)
{
case FIFO_DATA_8BIT:
memcpy(dat, &(((uint8 *)fifo->buffer)[fifo->max - temp_length]), temp_length);
memcpy(&(((uint8 *)dat)[temp_length]), &(((uint8 *)fifo->buffer)[fifo->head - *length]), (*length - temp_length));
break;
case FIFO_DATA_16BIT:
memcpy(dat, &(((uint16 *)fifo->buffer)[fifo->max - temp_length]), temp_length * 2);
memcpy(&(((uint16 *)dat)[temp_length]), &(((uint16 *)fifo->buffer)[fifo->head - *length]), (*length - temp_length) * 2);
break;
case FIFO_DATA_32BIT:
memcpy(dat, &(((uint32 *)fifo->buffer)[fifo->max - temp_length]), temp_length * 4);
memcpy(&(((uint32 *)dat)[temp_length]), &(((uint32 *)fifo->buffer)[fifo->head - *length]), (*length - temp_length) * 4);
break;
}
}
if(flag == FIFO_READ_AND_CLEAN) // 如果选择读取并更改 FIFO 状态
{
if(FIFO_CLEAR & fifo->execution)
{
return_state = FIFO_CLEAR_UNDO;
break;
}
fifo->execution |= FIFO_CLEAR;
fifo_end_offset(fifo, (fifo->max - fifo->size));
fifo->size = fifo->max;
fifo->execution &= ~FIFO_CLEAR;
}
}while(0);
fifo->execution &= FIFO_READ;
return return_state;
}
//-------------------------------------------------------------------------------------------------------------------
// 函数简介 FIFO 初始化 挂载对应缓冲区
// 参数说明 *fifo FIFO 对象指针
// 参数说明 type FIFO 数据位数
// 参数说明 *buffer_addr 要挂载的缓冲区
// 参数说明 size 缓冲区大小
// 返回参数 fifo_state_enum 操作状态
// 使用示例 fifo_init(&user_fifo, user_buffer, 64);
// 备注信息
//-------------------------------------------------------------------------------------------------------------------
fifo_state_enum fifo_init (fifo_struct *fifo, fifo_data_type_enum type, void *buffer_addr, uint32 size)
{
zf_assert(fifo != NULL);
fifo_state_enum return_value = FIFO_SUCCESS;
do
{
if(NULL == buffer_addr)
{
return_value = FIFO_BUFFER_NULL;
break;
}
fifo->buffer = buffer_addr;
fifo->execution = FIFO_IDLE;
fifo->type = type;
fifo->head = 0;
fifo->end = 0;
fifo->size = size;
fifo->max = size;
}while(0);
return return_value;
}