#ifndef __QUEUE_H
#define __QUEUE_H

/**@brief   队列模式类型
 * @details 
 *          Also, it keeps the information about which memory is allocated for the buffer
 *          and its size. This structure must be initialized by app_fifo_init() before use.
 */
typedef enum
{
    QUEUE_MODE_OVERFLOW,        //!< If the queue is full, new element will overwrite the oldest.
    QUEUE_MODE_NO_OVERFLOW,     //!< If the queue is full, new element will not be accepted.
} queue_mode_t;
/**@brief   A FIFO instance structure.
 * @details Keeps track of which bytes to read and write next.
 *          Also, it keeps the information about which memory is allocated for the buffer
 *          and its size. This structure must be initialized by app_fifo_init() before use.
 */
typedef enum
{
	size_4 		  = 0x0004U,
	size_8 		  = 0x0008U,
	size_16 		= 0x0010U,								 	                            
	size_32 		= 0x0020U,
	size_64 		= 0x0040U,
	size_128 		= 0x0080U,
  size_256 		= 0x0100U,         
	size_512 		= 0x0200U,
	size_1024 	= 0x0400U,
	size_2048 	= 0x0800U,
	size_4096 	= 0x1000U,
	size_8192 	= 0x2000U,
	size_16384	= 0x4000U,
	size_32768	= 0x8000U,
} queue_size_t;

typedef struct
{
  volatile unsigned short front;          //!< Queue front index.
  volatile unsigned short back;           //!< Queue back index.
	void           		* p_buffer;          //!< Pointer to the memory that is used as storage.
	queue_size_t  		size;              //!< Size of the queue.
	unsigned short    element_count;
	unsigned short  	element_size;      //!< Size of one element.
	queue_mode_t      mode;
} queue_t;

/******************************API 接口*************************************/
#define QUEUE_DEF(element_type, _name, _size, _mode)        \
				element_type   _name##_queue_buffer[(_size)];      	\
				queue_t _name=                             					\
								{                             							\
									.front 					= 0,              				\
									.back 					= 0,                    	\
									.p_buffer 			= _name##_queue_buffer,   \
									.size  					= (_size),          			\
									.element_count	= 0,											\
									.element_size   = sizeof(element_type),   \
									.mode           = _mode,       						\
								}    

//元素进队列
unsigned short queue_in(queue_t * p_queue, void const * p_element);
//元素出队列
unsigned short queue_out(queue_t * p_queue, void * p_element);
//查看队列中最后一个元素，队列中元素并没有减少
unsigned short queue_peek(queue_t * p_queue, void * p_element);
//清空队列
void queue_reset(queue_t * p_queue);	
//获取队列中元素个数
unsigned short queue_element_count(queue_t * p_queue);	
//查看队列中指定数组下标的元素的从最早进入队列的元素下标index==0开始算								
unsigned short queue_read(queue_t * p_queue, void * p_element ,int index);		
//扔掉掉列最后一个元素								
unsigned short queue_throw_element(queue_t * p_queue);
#endif 
