/*********************************************************
//file		:hd_dev_gpio.c
//author	:libo
//date		:2020/05/10
//version	:V1.0
//brief		:GSP HARD层GPIO接口C文件
*********************************************************/
/* Includes-----------------------------------------------------------------------------------*/
#include "main.h"


#ifdef USE_QUEUE_RECORD
/* Includes-----------------------------------------------------------------------------------*/
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "func_queue_record.h"
#include "func_lfs_record.h"
#include "func_spi_w25qxx.h"
#include "obj_hal_w25qxx.h"
#include "obj_soft_w25qxx.h"
#include "lib_ringfs_func.h"

/* Private macro------------------------------------------------------------------------------*/

#define DEBUG_RECORD_QUEUE  0

/* Private typedef----------------------------------------------------------------------------*/

record_queue_object lifo_queue_obj = {0};
record_queue_object fifo_queue_obj = {0};

/* Private define-----------------------------------------------------------------------------*/
/* Private variables--------------------------------------------------------------------------*/
/* Private function prototypes----------------------------------------------------------------*/

typedef struct queue_record_object
{
	uint8_t 	link_ok; 				//用于标识当前状态是1：读取，0：写入；
	uint8_t   flash_ok;					//存储器状态标志
	uint32_t 	running;
	uint32_t 	wr_idx;
	uint32_t 	msg_cnt;
	uint32_t 	wr_cnt;
	uint32_t 	rd_cnt;
	uint8_t 	opt_flag;
	char 			buf[QUEUE_MSG_ITEM_SIZE];
	uint32_t 	buf_len;
	int32_t 	(*flash_pop) (void *buf, uint32_t len);
	int32_t 	(*flash_push)(void *buf, uint32_t len);
}queue_record_object;
	
queue_record_object queue_record_obj = {
	.link_ok  = false,
	.flash_ok = false,
	.wr_cnt		= 0,
	.rd_cnt		= 0,
};


void func_record_queue_test(void)
{	
	uint8_t data = 0;
	uint32_t *p_data = 0;
	
	UNUSED(data);
	
	//sprintf(queue_record_obj.buf,"XX%02xXX",queue_record_obj.running%0x100);
	switch(queue_record_obj.opt_flag)
	{
		case 0:
		{			
			queue_record_obj.wr_idx++;
			//queue_record_obj.wr_idx = queue_record_obj.wr_cnt%0x100;
			//data = (uint8_t) queue_record_obj.wr_idx ;
			p_data = (uint32_t *)&queue_record_obj.buf[0];
			for(uint32_t i = 0; i < sizeof(queue_record_obj.buf)/4; i++ )
			{
				*p_data = queue_record_obj.wr_idx ;
				p_data++;
			}
			//memset((uint8_t *)queue_record_obj.buf, data ,sizeof(queue_record_obj.buf));
			func_record_queue_write((uint8_t *)queue_record_obj.buf ,sizeof(queue_record_obj.buf));
		}break;
		default:
		{
			func_record_queue_read((void *)queue_record_obj.buf ,sizeof(queue_record_obj.buf));
		}break;		
	}	

}

//Message_Queue队列初始化
void func_record_queue_init(void)
{

	taskENTER_CRITICAL();   //进入临界区
	
	lifo_queue_obj.hQueue = xQueueCreate(QUEUE_MSG_Q_NUM,QUEUE_MSG_ITEM_SIZE); //创建消息Message_Queue,队列项长度是串口接收缓冲区长度
	fifo_queue_obj.hQueue = xQueueCreate(QUEUE_MSG_Q_NUM,QUEUE_MSG_ITEM_SIZE); //创建消息Message_Queue,队列项长度是串口接收缓冲区长度

	taskEXIT_CRITICAL();    //退出临界区
#if 	USE_LFS_RECORD==1
	
	queue_record_obj.flash_pop 	= func_record_lfs_remove;
	queue_record_obj.flash_push = func_record_lfs_write;
	
#elif USE_RFS_RECORD==1
	queue_record_obj.flash_pop 	= lib_ringfs_pop;
	queue_record_obj.flash_push = lib_ringfs_push;	
#endif
	
}



//查询Queue队列中的总队列数量和剩余队列数量
void func_record_queue_check(record_queue_object * queue_obj)
{
	if(queue_obj->hQueue == NULL)
	{
		return;
	}
	
	QueueHandle_t xQueue = queue_obj->hQueue;	
	
	taskENTER_CRITICAL();   //进入临界区

	queue_obj->remain_size = uxQueueSpacesAvailable(xQueue);//得到队列剩余大小
	queue_obj->used_size = uxQueueMessagesWaiting(xQueue);//得到队列剩余大小
	queue_obj->total_size=uxQueueMessagesWaiting(xQueue)+uxQueueSpacesAvailable(xQueue);//得到队列总大小，总大小=使用+剩余的。
	
	taskEXIT_CRITICAL();    //退出临界区
}
void func_record_queue_empty(record_queue_object * queue_obj)
{
	if(queue_obj->hQueue == NULL)
	{
		return;
	}
	taskENTER_CRITICAL();   //进入临界区
	
#if 0	
	int32_t  num_cnt = QUEUE_MSG_Q_NUM;
	BaseType_t err = pdPASS;

	do
	{
		num_cnt--;
		if(num_cnt<=0)
		{
			break;
		}
			
		err = xQueueReceive(queue_obj->hQueue, (uint8_t *)queue_record_obj.buf, 0);
	}while(err == pdPASS);
#endif
	xQueueReset(queue_obj->hQueue);
	
	taskEXIT_CRITICAL();    //退出临界区
}

void func_record_queue_update(void)
{
	func_record_queue_check(&lifo_queue_obj);
	func_record_queue_check(&fifo_queue_obj);
	
	if(fifo_queue_obj.remain_size == 0)			//如果缓冲队列无空闲测请理缓冲区；
	{	
			func_record_queue_empty(&fifo_queue_obj);
	}
	
	if(lifo_queue_obj.remain_size == 0)
	{
			func_record_queue_empty(&lifo_queue_obj);
	}
	
	return;
}




//将产生的数据写入内存缓冲区队列
uint32_t func_record_queue_write(void *buf ,uint32_t len)
{	
	BaseType_t err;
	
	//有数据写入队列，则说明当前连接断开
	func_record_queue_link_set(false);
	
	if((lifo_queue_obj.hQueue == NULL)||(fifo_queue_obj.hQueue == NULL))
	{
		return 0;
	}
	
	if(lifo_queue_obj.used_size == 0)
	{
		err=xQueueSend(fifo_queue_obj.hQueue,(uint8_t *)buf,10);
	}
	else
	{
		err=xQueueSendToFront(lifo_queue_obj.hQueue,(uint8_t *)buf,10);
	}
	
	//写入个数累加
	queue_record_obj.wr_cnt++;
	
	func_record_queue_update();
	
	if(err != pdPASS)
	{
		return 0;
	}

	return len;
}



void func_record_queue_cpy(record_queue_object * des, record_queue_object * src)
{
	BaseType_t xResult = pdPASS;		
	do{		
		xResult = xQueueReceive(src->hQueue, (uint8_t *)queue_record_obj.buf, 0);
		if(xResult == pdPASS)
		{
			xResult = xQueueSendToFront(des->hQueue, (uint8_t *)queue_record_obj.buf, 0);
		}
	}while(xResult == pdPASS);
	
	func_record_queue_update();
	
	return;
}

//从队列中取出数据，发送；
uint32_t func_record_queue_read(void *buf ,uint32_t len)
{
	
	//从队列读取，则说明当前连接正常
	func_record_queue_link_set(true);	

	BaseType_t xResult = pdPASS;
	
	if((lifo_queue_obj.hQueue == NULL)||(fifo_queue_obj.hQueue == NULL))
	{
		return 0;
	}
	
	if(lifo_queue_obj.used_size == 0)
	{
		if(fifo_queue_obj.used_size > 0)
		{
			func_record_queue_cpy(&lifo_queue_obj, &fifo_queue_obj);
		}
	}
	
  xResult = xQueueReceive(lifo_queue_obj.hQueue, (uint8_t *)buf, 1);	
	
	//读取个数累加
	queue_record_obj.rd_cnt++;
	
	func_record_queue_update();
	
	if(xResult != pdPASS)
	{
		return 0;
	}

	return len;
}


//将缓存队列中的数据写入文件
void func_record_queue_to_flash(record_queue_object * queue_obj)
{
	BaseType_t xResult = pdPASS;
	do{
		xResult = xQueueReceive(queue_obj->hQueue,queue_record_obj.buf,1);
		if(xResult == pdPASS)
		{
			queue_record_obj.flash_push((uint8_t *)queue_record_obj.buf ,QUEUE_MSG_ITEM_SIZE);
		}
	}while(xResult == pdPASS);
	
	return;
}

void func_record_queue_link_set(uint8_t stat)
{	
	queue_record_obj.link_ok = stat;
	return ;
}

uint8_t func_record_queue_link_get(void)
{	
	return queue_record_obj.link_ok;
}

uint8_t func_record_queue_flash_set(uint8_t stat)
{	
	queue_record_obj.flash_ok = stat;
	return queue_record_obj.flash_ok;
}

uint8_t func_record_queue_flash_get(void)
{	
	//queue_record_obj.flash_ok = func_w25q_stat();
	
	return queue_record_obj.flash_ok;
}

uint32_t func_record_queue_cnt(void)
{
	uint32_t cnt_estimate = 0;
	
	if(queue_record_obj.wr_cnt > queue_record_obj.rd_cnt)
	{
		queue_record_obj.msg_cnt = queue_record_obj.wr_cnt - queue_record_obj.rd_cnt;
	}
	else
	{
		queue_record_obj.wr_cnt = 0;
		queue_record_obj.rd_cnt = 0;
		queue_record_obj.msg_cnt = 0;
	}
	
	//修正估算值
	cnt_estimate = lib_ringfs_obj_cnt_estimate();
	if(queue_record_obj.msg_cnt > cnt_estimate)
	{
		queue_record_obj.msg_cnt = cnt_estimate;
	}
	
	
	return queue_record_obj.msg_cnt ;
}

void func_record_queue_work(void)
{	

	BaseType_t xResult;

	//更新队列状态
	func_record_queue_update();	
	
	if(func_record_queue_link_get() == true)
	{
			//如果连接正常
			if((lifo_queue_obj.used_size == 0)&&(fifo_queue_obj.used_size == 0))
			{
				queue_record_obj.buf_len = queue_record_obj.flash_pop((uint8_t *)queue_record_obj.buf ,QUEUE_MSG_ITEM_SIZE);
				
				if(queue_record_obj.buf_len == QUEUE_MSG_ITEM_SIZE)
				{
					xResult = xQueueSend(lifo_queue_obj.hQueue,queue_record_obj.buf,10);					
				}								
			}	
	}
	else
	{
			//如果连接断开
			if(lifo_queue_obj.used_size >= (lifo_queue_obj.total_size/2))
			{	
					if(fifo_queue_obj.used_size > 0)
					{
						func_record_queue_to_flash(&fifo_queue_obj);
						func_record_queue_check(&fifo_queue_obj);
					}
					
					if(fifo_queue_obj.used_size == 0)
					{
						func_record_queue_cpy(&fifo_queue_obj, &lifo_queue_obj);
					}					
			}			
			
			if(fifo_queue_obj.used_size >= (fifo_queue_obj.total_size/2))
			{
				func_record_queue_to_flash(&fifo_queue_obj);
			}
	}
	
	func_record_queue_update();	
	UNUSED(xResult);	
	
	return;	
}

void func_record_queue_main(void const *argument)
{
		
	func_record_queue_init();
	func_record_queue_update();
	
#if USE_LFS_RECORD==1
	
#elif USE_RFS_RECORD==1	
	func_w25q_init();

	if((func_w25q_stat() == false)				//flash ID 异常
		||(func_w25q_bootcnt() == false))		//启动次数异常；
	{
		//设置flash状态为异常
		func_record_queue_flash_set(false);
		while(1)
		{
			osDelay(10000);
		}
	}

	//设置flash状态为正常
	func_record_queue_flash_set(true);
	
	lib_ringfs_init(QUEUE_MSG_ITEM_SIZE);	
	
	queue_record_obj.wr_cnt = lib_ringfs_obj_cnt_exact();
#endif
	
	while(1)
	{
		queue_record_obj.running++;
		
		if(queue_record_obj.running%(60) == 0)
		{
			if(func_w25q_stat() == false)			//读取FLASH ID,如果ID异常，则说明FLASH状态异常
			{
				//设置flash状态为异常
				func_record_queue_flash_set(false); 
			}				
		}
		
		
		if(queue_record_obj.flash_ok == true)			//flash正常，且处于读取状态时进行数量计算；			
		{		
			func_record_queue_cnt();
			
			func_record_queue_work();	
			
#if  DEBUG_RECORD_QUEUE==1		
		func_record_queue_test();			
		osDelay(10);
#else
		osDelay(1000);
#endif					
			
		}
		else
		{
			osDelay(10000);
		}
		

	}
	

}


#endif    /*************USE_QUEUE_RECORD*******************/

//------------------------the end of file-------------------------//
