/*                                                                          */
/*                                                                          */
/* Function    : define utilities to cyclic buffers                         */
/*                                                                          */
/*               Buffer Features:                                           */
/*                 1) Entries number is a power of 2                        */
/*                 2) Entries size is DW align                              */
/*                 2) Buffer start address is DW align                      */
/*                 3) Read and Write process can be asychronous             */
/*                 4) buffer data area and buffer header area are supplied  */
/*                    by user                                               */
/*                 5) no protection against write to full buffer            */
/*                 6) no protection against read from empty buffer          */
/*                                                                          */
/*                                +---------+                               */
/*                                |         |                               */
/*                                |         |                               */
/*                                |         |                               */
/*   +------------+               |         |                               */
/*   |            |     +-------->|         |                               */
/*   |            |     |         |         |                               */
/*   | read_index |-----+         |         |                               */
/*   |            |               |         |                               */
/*   | write_index|-------------->|         |                               */
/*   |            |               |         |                               */
/*   | Header     |               |         |                               */
/*   | Area       |               |         |                               */
/*   +------------+               |         |                               */
/*                                |Data     |                               */
/*                                |Area     |                               */
/*                                +---------+                               */
/*                                                                          */
/*  Available macros:                                                       */
/*   1) MBDR_DSP_CYCLIC_BUFFER_GET_READ_PTR_M(PI_CYCLIC_BUFFER_HDR_P)    */
/*   2) MBDR_DSP_CYCLIC_BUFFER_GET_WRITE_PTR_M(PI_CYCLIC_BUFFER_HDR_P)   */
/*   3) MBDR_DSP_CYCLIC_BUFFER_GET_ROOM_M(PI_CYCLIC_BUFFER_HDR_P)        */
/*                                                                          */
/*  Available routines:                                                     */
/*    1) void mbdr_dsp_cyclic_buf_config(                                */
/*                SHORT                          pi_entries_number,         */
/*                SHORT                          pi_entry_byte_size,        */
/*                void                          *pi_buffer_data_area_p,     */
/*                mbdr_dsp_cyclic_buf_hdr_t  *po_buffer_header_area_p);     */
/*                                                                          */
/*    2)2.1 void mbdr_dsp_cyclic_buf_write(                                 */
/*                   void                          *pi_data_p,              */
/*                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p)   */
/*      2.2 void mbdr_dsp_cyclic_buf_config_struct(                         */
/*              mbdr_dsp_cyclic_buf_config_io_params_t                      */
/*                              *pio_cyclic_buf_config_io_params_p);        */
/*                                                                          */
/*    3)void mbdr_dsp_cyclic_buf_read(                                      */
/*                   void  *po_read_data_p,                                 */
/*                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p)   */
/*                                                                          */
/*    4) SHORT mbdr_dsp_cyclic_buffer_get_room(                             */
/*                   (mbdr_dsp_cyclic_buf_hdr_t  *pi_cyclic_buffer_hdr_p)   */
/*                                                                          */
/*    5)  void mbdr_dsp_cyclic_buf_increment_read_index(                    */
/*                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p)   */
/*                                                                          */
/*    6)  void mbdr_dsp_cyclic_buf_increment_write_index(                   */
/*                 mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);    */
/*                                                                          */
/*    7) void mbdr_dsp_cyclic_buf_increment_read_index_by_given_value(      */
/*                   SHORT                       pi_increment_value,        */
/*                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);  */
/*    8) SHORT mbdr_dsp_cyclic_buffer_get_occupied_entries(                 */
/*                 mbdr_dsp_cyclic_buf_hdr_t  *pi_cyclic_buffer_hdr_p);     */
/*    9)void mbdr_dsp_cyclic_buf_read_n_dw_and_split(                       */
/*                   LONG  *po_read_dw_buf_0_p,                             */
/*                   LONG  *po_read_dw_buf_1_p,                             */
/*                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p)   */
/*                                                                          */
#include  "windef.h"
#include  "mbdr_dsp_utils.h"
#include  "mbdr_dsp_common_cyclic_buffer_header.h"

#ifndef  __MBDR_DSP_CYCLIC_BUFFER_H
#define  __MBDR_DSP_CYCLIC_BUFFER_H


/*the macro gets pointer to cyclic buffer head	*/
/*and element index in the buffer				*/
/*and returns pointer to desired element		*/
#define MBDR_DSP_CYCLIC_BUFFER_GET_ELEMENT_PTR_M(PI_CYCLIC_BUFFER_HDR_P, PI_ELEMENT_INDEX)\
         (  ((mbdr_dsp_cyclic_buf_hdr_t *)PI_CYCLIC_BUFFER_HDR_P)->buffer_base_p+\
           ((PI_ELEMENT_INDEX)\
		   *((mbdr_dsp_cyclic_buf_hdr_t *)PI_CYCLIC_BUFFER_HDR_P)->entry_byte_size))

/*the macro gets pointer to cyclic buffer head 				*/
/*and returns pointer to element to read (with read index)	*/
#define MBDR_DSP_CYCLIC_BUFFER_GET_READ_PTR_M(PI_CYCLIC_BUFFER_HDR_P)\
         MBDR_DSP_CYCLIC_BUFFER_GET_ELEMENT_PTR_M(PI_CYCLIC_BUFFER_HDR_P,\
          ((mbdr_dsp_cyclic_buf_hdr_t *)PI_CYCLIC_BUFFER_HDR_P)->read_index)

/*the macro gets pointer to cyclic buffer head 	*/
/*and returns the read index of the buffer		*/
#define MBDR_DSP_CYCLIC_BUFFER_GET_READ_INDEX_M(PI_CYCLIC_BUFFER_HDR_P)\
          ((mbdr_dsp_cyclic_buf_hdr_t *)PI_CYCLIC_BUFFER_HDR_P)->read_index

/*the macro gets pointer to cyclic buffer head 	*/
/*and returns the write index of the buffer		*/		  
#define MBDR_DSP_CYCLIC_BUFFER_GET_WRITE_INDEX_M(PI_CYCLIC_BUFFER_HDR_P)\
          ((mbdr_dsp_cyclic_buf_hdr_t *)PI_CYCLIC_BUFFER_HDR_P)->write_index


/*the macro gets pointer to cyclic buffer head 	*/
/*and returns '1' if cyclic buffer not empty	*/		  
#define MBDR_DSP_CYCLIC_BUFFER_CHECK_QUEUE_NOT_EMPTY_M(PI_CYCLIC_BUFFER_HDR_P)\
          (((mbdr_dsp_cyclic_buf_hdr_t *)PI_CYCLIC_BUFFER_HDR_P)->read_index\
		   !=\
           ((mbdr_dsp_cyclic_buf_hdr_t *)PI_CYCLIC_BUFFER_HDR_P)->write_index)

/*the macro gets pointer to cyclic buffer head 				*/
/*and returns pointer to element to write (with write index)*/		   
#define MBDR_DSP_CYCLIC_BUFFER_GET_WRITE_PTR_M(PI_CYCLIC_BUFFER_HDR_P)\
         MBDR_DSP_CYCLIC_BUFFER_GET_ELEMENT_PTR_M(PI_CYCLIC_BUFFER_HDR_P,\
          ((mbdr_dsp_cyclic_buf_hdr_t *)PI_CYCLIC_BUFFER_HDR_P)->write_index)

/* returns delta index consider arbitrary location */
/*    PI_CYCLIC_BUFFER_HDR_P  ->    */
/*    PI_ARBITRARY_INDEX      -     */
/*    PI_PLUS_DELTA_INDEX     -     */
/* returns delta index consider arbitrary location */
#define MBDR_DSP_CYCLIC_BUF_GET_GIVEN_RELATIVE_INDEX_M(PI_CYCLIC_BUFFER_HDR_P,\
		                                               PI_ARBITRARY_INDEX,\
		                                               PI_PLUS_DELTA_INDEX)\
          MBDR_DSP_UTILS_CYC_ADD_NO_CHANGE_M(PI_ARBITRARY_INDEX,\
        		                             PI_PLUS_DELTA_INDEX,\
                                             0,\
                                            (PI_CYCLIC_BUFFER_HDR_P)->entries_number-1)

/* configure & initialize cyclic buffer  */
/* getting parameters item by item       */
extern void mbdr_dsp_cyclic_buf_config(
                      SHORT                       pi_entries_number,
                      SHORT                       pi_entry_byte_size,
                      void                       *pi_buffer_data_area_p,
                      mbdr_dsp_cyclic_buf_hdr_t  *po_buffer_header_area_p);

/* configure & initialize cyclic buffer  */
/* getting parameters through structure  */
typedef struct _mbdr_dsp_cyclic_buf_config_io_params_t
{
   SHORT                       pi_entries_number;
   SHORT                       pi_entry_byte_size;
   void                       *pi_buffer_data_area_p;
   mbdr_dsp_cyclic_buf_hdr_t  *po_buffer_header_area_p;
}mbdr_dsp_cyclic_buf_config_io_params_t;
void mbdr_dsp_cyclic_buf_config_struct(
      mbdr_dsp_cyclic_buf_config_io_params_t *pio_cyclic_buf_config_io_params_p);


/* write item to cyclic buffer */
extern void mbdr_dsp_cyclic_buf_write(
                   void                          *pi_data_p,
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);

/* get item from cyclic buffer */
extern void mbdr_dsp_cyclic_buf_read(
                   void  *po_read_data_p,
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);

/* get N items from cyclic buffer */
extern void mbdr_dsp_cyclic_buf_read_n_items(
                   void                       *po_read_data_buf_p,
				   SHORT                       pi_items_number,
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);

/* writes N items into cyclic buffer */
extern void mbdr_dsp_cyclic_buf_write_n_items(
                   void                       *pi_write_data_buf_p,
				   SHORT                       pi_items_number,
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);


/* increment read_index by 1  of cyclic buffer */
extern void mbdr_dsp_cyclic_buf_increment_read_index(
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);

/* increment write_index by 1  of cyclic buffer */
extern void mbdr_dsp_cyclic_buf_increment_write_index(
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);


/* increment read index of cyclic buffer by given value */
extern void mbdr_dsp_cyclic_buf_increment_read_index_by_given_value(
                   SHORT                       pi_increment_value,
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);


/* increment write index of cyclic buffer by given value */
extern void mbdr_dsp_cyclic_buf_increment_write_index_by_given_value(
                   SHORT                       pi_increment_value,
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);

/* cyclic index addition                                    */
/* inputs: pi_index            - index_value                */
/*        pi_add_value         - add value                  */
/* output: value after cyclic addition                      */
extern SHORT mbdr_dsp_cyclic_buf_add(
                   SHORT   pi_index,
				   SHORT   pi_add_value,
                   mbdr_dsp_cyclic_buf_hdr_t  *pi_cyclic_buffer_hdr_p);

/* gets free entries in queue */
extern SHORT mbdr_dsp_cyclic_buffer_get_room(
                   mbdr_dsp_cyclic_buf_hdr_t  *pi_cyclic_buffer_hdr_p);

/* gets number of occupied entries in queue */
extern SHORT mbdr_dsp_cyclic_buffer_get_occupied_entries(
                   mbdr_dsp_cyclic_buf_hdr_t  *pi_cyclic_buffer_hdr_p);


/* recommanded pysical layer when when receiver and transmitter are the same */
extern void *mbdr_dsp_cyclic_buf_standat_c_memcpy(
                   void       *dst_p,
                   const void *src_p,
                   USHORT      pi_buf_data_size,
                   USHORT      pi_dummy_memcpy_code);

/* reads n DW from cyclic buffer and split output data to 2 different buffers:*/
/*  rather after routine:                                                     */
/*   po_read_even_index_buf_p:0, 2, 4, ....                                   */
/*   po_read_odd_index_buf_p:1, 3, 5, ....                                    */
/*                                                                            */
/* prerequisites: 1) pi_read_dw_number - is even                              */
/*                2) buffer is initialized in such a way that each entry is   */
/*                   LONG size                                                */
extern void mbdr_dsp_cyclic_buf_read_n_dw_and_split(
                   LONG  *po_read_even_index_buf_p,
                   LONG  *po_read_odd_index_buf_p,
                   SHORT  pi_read_dw_number,
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);


/* return pointer to element[cyclic_add(pi_start_index,  pi_delta_index)      */
/* backgrond: sometimes we are interested in location of element that we do   */
/*            not know its absolute value but we know its cyclic relative     */
/*            location                                                        */
extern void* mbdr_dsp_cyclic_buf_get_relative_pointer(
                      mbdr_dsp_cyclic_buf_hdr_t  *pi_cyclic_buffer_hdr_p,
                      SHORT                       pi_relative_element_index,
                      SHORT                       pi_gap);


/* routine manages passing on all occpied entries in cyclic buffer            */
/* and enable user to update each and inform wether it is still necessary     */
/* user may use these routine to through non interesting elements from queue  */
/* or to update data                                                          */
extern void mbdr_dsp_cyclic_buf_pass_filter_and_update(
             /* returns legal_f: 0 - filter   */
             /*                  1 - pass     */
             SHORT (*element_update_check_legal_f_proc_p)(void *pio_element),
             mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p);

/* function: return legal elements in cyclic buffer 				*/
/* input:    element_update_check_legal_f_proc_p-  					*/
/* 					procedure from application that gets pointer 	*/
/* 					to buff element and decides whether it hold 	*/
/* 					application condition or not. 					*/
/* 			 pi_entries_number_to_check- how many entries should 	*/
/* 					check in the buffer. 							*/
/* 			 pio_cyclic_buffer_hdr_p - pointer to cyc buf header 	*/
/* output:   number of legal elements- how many elements were legal */
/* 					until first failure. 							*/
/* description:		the function gets cuc buf header with some read */
/* 					index N and number of entries to check K. 		*/
/*					the function check the elements one by one for  */
/* 					app criterion and exit when all items passed    */
/* 					or first failure occures 						*/
extern SHORT mbdr_dsp_cyclic_buf_return_num_of_legal_items(
             SHORT (*element_update_check_legal_f_proc_p)(void *pio_element),
			 SHORT	pi_entries_number_to_check,
             mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p				);

/*the macro get read request, increment read*/
/*index (cyclically) and update free and 	*/
/*occupide entries							*/
#define MBDR_DSP_CYCLIC_BUF_INCREMENT_READ_INDEX_M(PIO_CYCLIC_BUFFER_HDR_P)\
  MBDR_DSP_UTILS_CYC_INC_M((PIO_CYCLIC_BUFFER_HDR_P)->read_index,\
                          0,\
                          (PIO_CYCLIC_BUFFER_HDR_P)->entries_number-1);\
  /* update _free & _occupied fields */\
  (PIO_CYCLIC_BUFFER_HDR_P)->synchronized_access_free_entries++;\
  (PIO_CYCLIC_BUFFER_HDR_P)->synchronized_access_occupied_entries--


/*the macro get write request, increment write	*/
/*index (cyclically) and update free and 		*/
/*occupide entries								*/
#define MBDR_DSP_CYCLIC_BUF_INCREMENT_WRITE_INDEX_M(PIO_CYCLIC_BUFFER_HDR_P)\
  MBDR_DSP_UTILS_CYC_INC_M((PIO_CYCLIC_BUFFER_HDR_P)->write_index,\
                          0,\
                          (PIO_CYCLIC_BUFFER_HDR_P)->entries_number-1);\
  /* update _free & _occupied fields */\
  (PIO_CYCLIC_BUFFER_HDR_P)->synchronized_access_free_entries--;\
  (PIO_CYCLIC_BUFFER_HDR_P)->synchronized_access_occupied_entries++

#define MBDR_DSP_CYCLIC_BUF_INCREMENT_READ_INDEX_BY_GIVEN_VALUE_M(PI_INCREMENT_VALUE,\
                                                                  PIO_CYCLIC_BUFFER_HDR_P)\
 MBDR_DSP_UTILS_CYC_ADD_M((PIO_CYCLIC_BUFFER_HDR_P)->read_index,\
                          PI_INCREMENT_VALUE,\
						  0,\
						  (PIO_CYCLIC_BUFFER_HDR_P)->entries_number-1);\
 /* update _free & _occupied fields */\
 (PIO_CYCLIC_BUFFER_HDR_P)->synchronized_access_free_entries += PI_INCREMENT_VALUE;\
 (PIO_CYCLIC_BUFFER_HDR_P)->synchronized_access_occupied_entries -= PI_INCREMENT_VALUE

#define MBDR_DSP_CYCLIC_BUF_INCREMENT_WRITE_INDEX_BY_GIVEN_VALUE_M(PI_INCREMENT_VALUE,\
                                                                  PIO_CYCLIC_BUFFER_HDR_P)\
 MBDR_DSP_UTILS_CYC_ADD_M((PIO_CYCLIC_BUFFER_HDR_P)->write_index,\
                          PI_INCREMENT_VALUE,\
						  0,\
						  (PIO_CYCLIC_BUFFER_HDR_P)->entries_number-1);\
 /* update _free & _occupied fields */\
 (PIO_CYCLIC_BUFFER_HDR_P)->synchronized_access_free_entries -= PI_INCREMENT_VALUE;\
 (PIO_CYCLIC_BUFFER_HDR_P)->synchronized_access_occupied_entries += PI_INCREMENT_VALUE

#define MBDR_DSP_CYCLIC_BUFFER_GET_NEXT_INDEX_M(PI_CYCLIC_BUFFER_HDR_P, PI_INDEX)\
		( (PI_INDEX == (PI_CYCLIC_BUFFER_HDR_P)->entries_number-1)?0:(PI_INDEX+1))

#define MBDR_DSP_CYCLIC_BUFFER_GET_NEXT_READ_INDEX_M(PI_CYCLIC_BUFFER_HDR_P)\
		MBDR_DSP_CYCLIC_BUFFER_GET_NEXT_INDEX_M(PI_CYCLIC_BUFFER_HDR_P,\
                                               (PI_CYCLIC_BUFFER_HDR_P)->read_index)

#define MBDR_DSP_CYCLIC_BUFFER_GET_PREVIOUS_READ_INDEX_M(PI_CYCLIC_BUFFER_HDR_P)\
          MBDR_DSP_UTILS_CYC_DEC_M((PI_CYCLIC_BUFFER_HDR_P)->read_index,\
                                   0,\
                                   (PI_CYCLIC_BUFFER_HDR_P)->entries_number-1)



/* copy the following fields from 1 header to the other :  */
/*   1) read_index                                         */
/*   2) write_index                                        */
/*   3) synchronized_access_free_entries                   */
/*   4) synchronized_access_occupied_entries               */
#define MBDR_DSP_CYCLIC_BUFFER_COPY_INDEX_COUNTERS_M(PI_CYCLIC_BUFFER_HDR_P,\
                                                     PO_CYCLIC_BUFFER_HDR_P)\
          (PO_CYCLIC_BUFFER_HDR_P)->read_index\
		    = (PI_CYCLIC_BUFFER_HDR_P)->read_index;\
          (PO_CYCLIC_BUFFER_HDR_P)->write_index\
		    = (PI_CYCLIC_BUFFER_HDR_P)->write_index;\
          (PO_CYCLIC_BUFFER_HDR_P)->synchronized_access_free_entries\
		    = (PI_CYCLIC_BUFFER_HDR_P)->synchronized_access_free_entries;\
          (PO_CYCLIC_BUFFER_HDR_P)->synchronized_access_occupied_entries\
		    = (PI_CYCLIC_BUFFER_HDR_P)->synchronized_access_occupied_entries

/* return: 0: FIFO is     empty */
/*         1: FIFO is not empty */
#define  MBDR_DSP_CYCLIC_BUF_CHECK_OCCUPID_M(\
                      PI_CLOSE_BUFFER_HEADER_AREA_P)\
  ( ((PI_CLOSE_BUFFER_HEADER_AREA_P)->read_index)\
     !=\
	((PI_CLOSE_BUFFER_HEADER_AREA_P)->write_index))

/* return: 0: FIFO is not full */
/*         1: FIFO is     full */
#define  MBDR_DSP_CYCLIC_BUF_CHECK_FULL_M(PI_CLOSE_BUFFER_HEADER_AREA_P)\
  (  ( ( (PI_CLOSE_BUFFER_HEADER_AREA_P)->read_index\
        -(PI_CLOSE_BUFFER_HEADER_AREA_P)->write_index)\
      ==1)\
     |\
       (( (PI_CLOSE_BUFFER_HEADER_AREA_P)->write_index\
         -(PI_CLOSE_BUFFER_HEADER_AREA_P)->read_index)\
        ==(PI_CLOSE_BUFFER_HEADER_AREA_P)->entries_number-1))

#endif
