


/*                                                                          */
/* Function    : define general utilities                                   */
/*                                                                          */
/* Macros      1) MBDR_DSP_UTILS_M_WRITE_32BIT(PI_DATA, PO_MEM_P)           */
/*                                                                          */
/*  Available routines:                                                     */
/*    1) void* mbdr_dsp_utils_memcpy_dw_by_dw(void       *po_dst_buf_p,     */
/*                                     const void *pi_src_buf_p,            */
/*                                     size_t      pi_buf_byte_size)        */
/*                                                                          */
/*    2) void mbdr_dsp_utils_nop_wait(LONG pi_wait_cycles)                  */
/*                                                                          */
/*    3) void mbdr_dsp_utils_poll_dw_with_wait(                             */
/*                  volatile LONG *pi_poll_dw_p,                            */
/*                  LONG           pi_poll_dw_value,                        */
/*                  LONG           pi_wait_cycles_between_read_access)      */
/*                                                                          */
/*    4) void mbdr_dsp_set_bits_sequence_in_packed_bits_array(              */
/*                                    ULONG  pi_first_set_bit_index,        */
/*	       						      LONG   pi_set_bits_number,            */
/*                                    ULONG *pio_packed_bits_array_p);      */

#include  "windef.h"
#include  "string.h"
#ifndef _MBDR_DSP_UTILS_H
#define _MBDR_DSP_UTILS_H



#define MBDR_DSP_UTILS_ALL_ENABLE_FFFFFFFF (~0)
#define MBDR_DSP_UTILS_INT_MINUS_1         (~0)


/* returns cyclic difference between indexes of cyclic queue            */
/* Inputs: PI_CYCLIC_INDEX                - cyclic index                */
/*         PI_SUBTRAHEND_CYCLIC_INDEX     - subtrahend cyclic index     */
/* legal range is [0..PI_POWER_2_RELAVANT_BITS_MASK]                    */
/*                                                                      */
/*         PI_POWER_2_RELAVANT_BITS_MASK  - power 2 cyclic buffer mask examples: */
/*                                          for queue_size=8   insert 7  =0x007  */
/*                                          for queue_size=256 insert 255=0x0ff   */
/* output cyclic difference: (PI_CYCLIC_INDEX-PI_SUBTRAHEND_CYCLIC_INDEX) */
#define MBDR_DSP_UTILS_POWER_2_CYCLIC_DIFFEENCE_M(PI_CYCLIC_INDEX,\
		                                          PI_SUBTRAHEND_CYCLIC_INDEX,\
		                                          PI_POWER_2_RELAVANT_BITS_MASK)\
         ( ((PI_CYCLIC_INDEX)-(PI_SUBTRAHEND_CYCLIC_INDEX)) & (PI_POWER_2_RELAVANT_BITS_MASK) )


/* returns absolute cyclic distance between numbers                           */
/* for instance: MBDR_DSP_UTILS_POWER_2_ABS_CYCLIC_DISTANCE_M(0, 1, 0x7) = 1  */
/*               MBDR_DSP_UTILS_POWER_2_ABS_CYCLIC_DISTANCE_M(1, 0, 0x7) = 1  */
/*               MBDR_DSP_UTILS_POWER_2_ABS_CYCLIC_DISTANCE_M(6, 0, 0x7) = 2  */
/*               MBDR_DSP_UTILS_POWER_2_ABS_CYCLIC_DISTANCE_M(0, 6, 0x7) = 2  */
/*               MBDR_DSP_UTILS_POWER_2_ABS_CYCLIC_DISTANCE_M(7, 0, 0x7) = 1  */
/*               MBDR_DSP_UTILS_POWER_2_ABS_CYCLIC_DISTANCE_M(0, 7, 0x7) = 1  */
#define MBDR_DSP_UTILS_POWER_2_ABS_CYCLIC_DISTANCE_M(PI_PARAM_1, PI_PARAM_2, PI_RELEVANT_BITS_MASK)\
        (min(MBDR_DSP_UTILS_POWER_2_CYCLIC_DIFFEENCE_M(PI_PARAM_1, PI_PARAM_2, PI_RELEVANT_BITS_MASK),\
		     MBDR_DSP_UTILS_POWER_2_CYCLIC_DIFFEENCE_M(PI_PARAM_2, PI_PARAM_1, PI_RELEVANT_BITS_MASK)))

/* convert input data parameter to 32 bit and store it */
#define MBDR_DSP_UTILS_M_WRITE_32BIT_M(PI_DATA, PO_MEM_P)\
        *((LONG *)(PO_MEM_P))= (LONG)(PI_DATA)

/* copy 32 bit from source to destination */
#define MBDR_DSP_UTILS_M_COPY_32BIT_M(PO_DST_P, PI_SRC_P)\
        *((LONG *)(PO_DST_P))=  *((LONG *)(PI_SRC_P))


/* test and set a bit in packed bits array       */
/* copy the original value of interesting bit    */
#define MBDR_DSP_UTILS_BIT_TEST_AND_SET_IN_PACKED_ARRAY_M(\
          PIO_PACKED_ARRAY_32BIT_P, PI_BIT_NUMBER, PO_BIT_F)\
		  {\
		   LONG  mask;\
		   LONG *relevant_32bit_p;\
           relevant_32bit_p  = &(PIO_PACKED_ARRAY_32BIT_P)[PI_BIT_NUMBER/32] ;\
           mask              = 1 << ((PI_BIT_NUMBER) & 0x1f);\
		   PO_BIT_F          = ((mask & *relevant_32bit_p) != 0);\
          *relevant_32bit_p |= mask;\
          }

/* Writes input bit into 32 bits packed array  */
#define MBDR_DSP_UTILS_BIT_INSERT_INTO_PACKED_ARRAY_M(\
          PIO_PACKED_ARRAY_ULONG_32BIT_P, PI_BIT_NUMBER, PI_BIT)\
		  {\
		   ULONG  mask;\
		   ULONG *local_io_32bit_p;\
		   LONG   local_pi_bit_mod_32;\
		   local_io_32bit_p     = PIO_PACKED_ARRAY_ULONG_32BIT_P;\
		   local_io_32bit_p    += (PI_BIT_NUMBER) / MBDR_DSP_32;\
		   local_pi_bit_mod_32  = (PI_BIT_NUMBER) % MBDR_DSP_32;\
           mask              = ~(1 << local_pi_bit_mod_32);\
		   *local_io_32bit_p  = (*local_io_32bit_p & mask) | (((ULONG)((PI_BIT)&1)) << local_pi_bit_mod_32);\
          }

/* test and set a bit in packed bits array       */
#define MBDR_DSP_UTILS_BIT_TEST_IN_PACKED_ARRAY_M(\
  PI_PACKED_ARRAY_32BIT_P, PI_BIT_INDEX)\
   (MBDR_DSP_UTILS_BIT_TEST_M((PI_PACKED_ARRAY_32BIT_P)[(PI_BIT_INDEX)/32],\
                             ((PI_BIT_INDEX)&0x1f)))

/* clears bitfeild in DW */
#define MBDR_DSP_UTILS_CLEAR_BIT_FEILD_M(\
          PI_INPUT_32BIT, PI_LSB_CLEAR_BIT_INDEX, PI_RESET_BITS_NUMBER)\
		  ((PI_INPUT_32BIT)\
		  &\
		  (~((((ULONG)0xffffffff)>>(32-(PI_RESET_BITS_NUMBER)))\
              <<\
             (PI_LSB_CLEAR_BIT_INDEX))))

/* sets bitfeild in DW */
#define MBDR_DSP_UTILS_SET_BIT_FEILD_M(\
          PI_INPUT_32BIT, PI_BIT_FIELD_OFS, PI_BIT_FIELD_SIZE)\
		  ((PI_INPUT_32BIT)\
		  |\
		  (((((ULONG)0xffffffff)>>(32-(PI_BIT_FIELD_SIZE)))\
              <<\
             (PI_BIT_FIELD_OFS))))

/* extracts unsigned bitfeild from DW */
#define MBDR_DSP_UTILS_EXTRACTU_BIT_FEILD_M(\
          PI_INPUT_32BIT, PI_BIT_FIELD_OFS, PI_BIT_FIELD_SIZE)\
		  ( ((PI_INPUT_32BIT)>>(PI_BIT_FIELD_OFS))\
		    &\
            ( (1<<(PI_BIT_FIELD_SIZE)) - 1))

/* inserts bit field to required location */
#define MBDR_DSP_UTILS_INSERT_BIT_FEILD_M(\
    PI_SRC_BITFIELD_32BIT, PI_BIT_FIELD_OFS, PI_BIT_FIELD_SIZE, PIO_32BIT_NUMBER)\
		  (  (MBDR_DSP_UTILS_CLEAR_BIT_FEILD_M(\
              PIO_32BIT_NUMBER, PI_BIT_FIELD_OFS, PI_BIT_FIELD_SIZE))\
            +\
             (((ULONG)(MBDR_DSP_UTILS_EXTRACTU_BIT_FEILD_M(PI_SRC_BITFIELD_32BIT,\
                                                  0,\
                                                  PI_BIT_FIELD_SIZE)))\
			  << PI_BIT_FIELD_OFS))

/* returns last dword index of 32 bit packed array */
/* restriction: PI_ARRAY_BITS_NUMBER > 0           */
#define MBDR_DSP_UTILS_VEC_BITS_GET_LAST_DWORD_INDEX_M(\
          PI_ARRAY_BITS_NUMBER)\
  	      ((PI_ARRAY_BITS_NUMBER)/MBDR_DSP_32)-(((PI_ARRAY_BITS_NUMBER)%MBDR_DSP_32)==0)

/* clears unused bits in last DW packed bits array      */
/* PIO_PACKED_BITS_DW_P      -> packed bits array       */
/* PI_ARRAY_USED_BITS_NUMBER - number of used bits      */
#define MBDR_DSP_UTILS_VEC_BITS_CLEAR_UNUSED_BITS_IN_DW_PACKED_ARRAY_M(\
          PIO_PACKED_BITS_DW_P, PI_ARRAY_USED_BITS_NUMBER)\
		  PIO_PACKED_BITS_DW_P[\
		    MBDR_DSP_UTILS_VEC_BITS_GET_LAST_DWORD_INDEX_M(PI_ARRAY_USED_BITS_NUMBER)]=\
          MBDR_DSP_UTILS_CLEAR_BIT_FEILD_M(\
            PIO_PACKED_BITS_DW_P[\
            MBDR_DSP_UTILS_VEC_BITS_GET_LAST_DWORD_INDEX_M(PI_ARRAY_USED_BITS_NUMBER)],\
             (PI_ARRAY_USED_BITS_NUMBER)%MBDR_DSP_32,\
              ((MBDR_DSP_32-((PI_ARRAY_USED_BITS_NUMBER)%MBDR_DSP_32))%MBDR_DSP_32)  )

/* set a bit in packed bits array       */
#define MBDR_DSP_UTILS_SET_BIT_IN_PACKED_ARRAY_M(PIO_PACKED_ARRAY_32BIT_P, PI_BIT_NUMBER)\
		  (PIO_PACKED_ARRAY_32BIT_P)[(PI_BIT_NUMBER) >> 5] |= 1 << ((PI_BIT_NUMBER) & 0x1f)

#define MBDR_DSP_UTILS_RESET_BIT_IN_PACKED_ARRAY_M(PIO_PACKED_ARRAY_32BIT_P, PI_BIT_NUMBER)\
	(PIO_PACKED_ARRAY_32BIT_P)[(PI_BIT_NUMBER) >> 5] &= (~( 1 << ((PI_BIT_NUMBER) & 0x1f) ))

#define MBDR_DSP_BIT_OR_WITH_VAL_IN_S32_ARRAY_M(PI_BIT_INDEX, PI_S32_ARR_P,PI_BIN_VAL)\
	( ((PI_S32_ARR_P)[(((PI_BIT_INDEX)) >> 5)]) |= ( (PI_BIN_VAL) << (((PI_BIT_INDEX))%32) ) )

/* this macro finds modulu of arbitrary integer x  	*/
/* with number which is power of 2. 				*/
/* x%y where x integer and y = 2^n 					*/


/* rounds up to close factor of required power 2 */
/* examples: 20 = MBDR_DSP_ROUND_UP_TO_CLOSE_POWER_2_FACTOR_M(17, 4)    */
/*           16 = MBDR_DSP_ROUND_UP_TO_CLOSE_POWER_2_FACTOR_M(16, 4)    */
#define MBDR_DSP_ROUND_UP_TO_CLOSE_POWER_2_FACTOR_M(PI_NUMBER, PI_POWER_2)\
         ( (((PI_NUMBER)+((PI_POWER_2)-1))) & (~((PI_POWER_2)-1)) )

/* returns requed packed array size    */
#define MBDR_DSP_UNPACK_SIZE_2_PACK_SIZE_M(PI_NUMBER,\
                                           PI_POWER_2_OF_BITS_NUMBER_IN_PACKED_ELEMENT)\
        ( MBDR_DSP_ROUND_UP_TO_CLOSE_POWER_2_FACTOR_M(\
                                 (PI_NUMBER),\
                                 (PI_POWER_2_OF_BITS_NUMBER_IN_PACKED_ELEMENT)))\
         /(PI_POWER_2_OF_BITS_NUMBER_IN_PACKED_ELEMENT)

/* resets requiren N least significant bits    */
#define    MBDR_DSP_UTILS_RESET_N_LEAST_SIGNIFICANT_BITS_M(PI_DATA, PI_MASK_BITS_NUMBER)\
            ((PI_DATA) & ( (0xFFFFFFFF) << (PI_MASK_BITS_NUMBER) ))


/* memcpy 32 bit by 32 bit */
extern void* mbdr_dsp_utils_memcpy_dw_by_dw(void       *po_dst_buf_p,
                                     const void *pi_src_buf_p,
                                     size_t      pi_buf_byte_size);

/* wait a required number of cycles, in a nop loop   */
extern void mbdr_dsp_utils_nop_wait(LONG pi_wait_cycles);

/* routine that do nothing */
extern void mbdr_dsp_utils_nop(void);

/* poll memory location till it get a given value,   */
/* perform a required nops between read accesses     */
extern void mbdr_dsp_utils_poll_dw_with_wait(
                     volatile LONG *pi_poll_dw_p,
                     LONG           pi_poll_dw_value,
                     LONG           pi_wait_cycles_between_read_access);

/* sets bits sequence in packed bits array           */
extern void mbdr_dsp_vec_set_bits_sequence(
                                      ULONG  pi_first_set_bit_index,
									  LONG   pi_set_bits_number,
                                      ULONG *pio_packed_bits_array_p);


/*  macros list                                                          */
/*  CYC_INC_D - cyclic inc macro.                                        */
/*       usage : CYC_INC_D (pio_param, lowest_val, highest_val);         */
/*  BIT_TEST_D - test selected bit macro (return 0 forreset, 1 for set)  */
/*          usage : BIT_TEST_M(PI_INPUT_BINARY_PARAMETER, PI_TEST_BIT_NUM)*/
/*  BIT_SET_D - set selected bit.                                        */
/*       usage : BIT_SET_M(PI_INPUT_BINARY_PARAMETER, PI_SET_BIT_NUM)    */
/*  BIT_RESET_D - reset selected bit                                     */
/*       usage : BIT_RESET_M(PI_INPUT_BINARY_PARAMETER, PI_RESET_BIT_NUM)*/
/*  BIN_CYCLIC_INC_D - returns binary cyclic inc of input param          */
/*       usage : BIN_CYCLIC_INC_M(pi_param, pi_max_value)                */
/* DIV_64K_D - returns div 64k result by shift needed for use check.     */
/*             usage : DIV_64K_M(pi_abslt_adrs_long)                     */
/* BIT_WRITE_D -  copy lsb bit of pi_new_bit_value to pi_modify_bit_number*/
/*                of pi_operand.                                          */
/*   usage : BIT_WRITE_M(pi_operand, pi_modify_bit_number, pi_new_bit_value)*/
/* procedures list                                                       */
/*   find_bits_num_in_word - return number of set bits of input word     */
/*        usage : find_bits_num_in_word(pi_word)                         */

/* cyclic increment of pio_param.                                         */
/*        function discription.                                           */
/*                                                                        */
/*        org values of pio_parm                        fine value        */
/*        pio_param < highest_val                       pio_param+1       */
/*        pio_param = highest_val                       lowest_val        */
/* remark : assume it input value is already in leagal range in           */
#define MBDR_DSP_UTILS_CYC_INC_M(pio_param, lowest_val, highest_val)\
        pio_param = (pio_param+1>highest_val)?lowest_val:(pio_param + 1)

/* cyclic deccrement of pio_param.                                         */
/* remark : assume it input value is already in leagal range in           */
#define MBDR_DSP_UTILS_CYC_DEC_M(pio_param, lowest_val, highest_val)\
          (pio_param == lowest_val)?highest_val:((pio_param)-1)

/* computes cyclic difference between two indexes of cyclic buffer    */
/* if both index parameters are equal two indexes of cyclic buffer    */
/* remark : assume it input values are in legal range                 */
#define MBDR_DSP_UTILS_CYC_DIFFERENCE_M(pi_subtrhend_index,\
                                        pi_sub_index,\
                                        lowest_val,\
                                        highest_val)\
  ((pi_subtrhend_index) > (pi_sub_index))\
   ?(pi_subtrhend_index)-(pi_sub_index)\
   :((highest_val)-(pi_sub_index)+(pi_subtrhend_index)-(lowest_val)+1)


/* returns cyclic addition                                               */
/*        function description.                                           */
/*                                                                        */
/*        org values of pio_parm                        fine value        */
/*        pio_param + pi_add_val <= highest_val         pio_param+1       */
/*        pio_param = highest_val                       lowest_val        */
/* remark : assume it input value is already in leagal range in           */
#define MBDR_DSP_UTILS_CYC_ADD_NO_CHANGE_M(pi_start_param, pi_add_val, pi_lowest_val, pi_highest_val)\
           ( (pi_start_param + (pi_add_val)) > (pi_highest_val))\
           ?((pi_lowest_val+pi_add_val+pi_start_param)-(pi_highest_val)-1)\
		   :(pi_start_param+pi_add_val)

/* cyclic add of pio_param                                                */
/*        function discription.                                           */
/*                                                                        */
/*        org values of pio_parm                        fine value        */
/*        pio_param + pi_add_val <= highest_val         pio_param+1       */
/*        pio_param = highest_val                       lowest_val        */
/* remark : assume it input value is already in leagal range in           */
#define MBDR_DSP_UTILS_CYC_ADD_M(pio_param, pi_add_val, pi_lowest_val, pi_highest_val)\
        pio_param = ( (pio_param + pi_add_val) > (pi_highest_val))\
           ?((pi_lowest_val+pi_add_val+pio_param)-(pi_highest_val)-1)\
		   :(pio_param+pi_add_val)

/* cyclic subtrucion of pio_param                                                */
/*        function discription.                                           */
/*                                                                        */
/*        org values of pio_parm        fine value        */
/*        pio_param - pi_sub_val < 0    pi_highest_val-pio_param-pi_sub_val  */
/*        pio_param = highest_val       lowest_val        */
/* remark : assume it input value is already in leagal range in           */
#define MBDR_DSP_UTILS_CYC_SUB_M(pio_param, pi_sub_val, pi_lowest_val, pi_highest_val)\
        pio_param = ( (pio_param - pi_sub_val) < 0)\
           ?(pi_highest_val-pio_param-pi_sub_val+1)\
		   :(pio_param-pi_sub_val)

/* dummy routine that does nothing  */
extern void mbdr_dsp_utils_nop_single_param(SHORT PI_PARAM);

/* dummy routine that does nothing  */
extern void mbdr_dsp_utils_nop_single_pointer_param(void *pi_dummy_p);

/* never read dummy LONG    */
extern LONG mbdr_dsp_utils_dummy;

/* never read dummy pointer */
extern void *mbdr_dsp_utils_dummy_p;

/* never read used for debug */
extern SHORT mbdr_dsp_utils_dbg_main_loop_index;

/* sum elements of input signed 32bit vector    */
/* pi_vec_byte_size_align_32 = 8, 16, 24, ..8K  */
extern LONG mbdr_dsp_vec_s32_sum_elements_aligned(
                  LONG  *pi_dw_vec_p,
                  LONG   pi_vec_byte_size_align_32);

/* returns maximum value/index out of 3 unsigned 32bits integer */
/* input:   pi_3_u32_vec_p -> 3 elements unsigned 32 bit vector */
/* outputs: po_max_index_p -> index of maximum value            */
/* return:                    maximum value                    */
extern ULONG mbdr_dsp_max3_u32(ULONG *pi_3_u32_vec_p,
                               CHAR  *po_max_index_p);

/*         +-------------------+                                            */
/*         |top_serial_number  |                                            */
/*         +-------------------+                                            */
/*         :                   :                                            */
/*         :data               :                                            */
/*         :                   :                                            */
/*         +-------------------+                                            */
/*         |base_serial_number |                                            */
/*         +-------------------+                                            */
/* if(top_serial_number != *pio_last_read_sync_number_p)                    */
/*    performs synchronized reading                                         */
/*    returns(1)                                                            */
/* else                                                                     */
/*    returns(0)                                                            */
/* input:1)  pi_src_buffer_p -> source buffer updated in linear order by    */
/*                             asychronous process                          */
/*       2)  pi_buffer_byte_size -> buffer byte size include base/top       */
/* input/output: value of base/top_serial_number in laset reading           */
/* output: *po_dst_buffer_p -> synchronized reading of source buffer        */
/* return: update_f  0: destination buffer was  not updated                 */
/*                   1:      -"-      -"-   -"- updated                     */
extern ULONG mbdr_dsp_read_base_top_sync_buffer_if_necessary(
                   volatile ULONG *pi_src_buffer_p,
                   ULONG           pi_buffer_byte_size,
                   ULONG          *pio_last_read_sync_number_p,
                   ULONG          *po_dst_buffer_p);


/*    performs synchronized reading anyway               */
extern void mbdr_dsp_read_base_top_sync_buffer_anyway(
                   volatile ULONG *pi_src_buffer_p,
                   ULONG           pi_buffer_byte_size,
                   ULONG          *po_last_read_sync_number_p,
                   ULONG          *po_dst_buffer_p);

/* state manage routine type */
typedef struct  _mbdr_dsp_proc_p_tbl_entry_t
{
  void (*proc_p)(void) ;
}mbdr_dsp_proc_p_tbl_entry_t;

/* returns binary cyclic inc of pi_param                                  */
/*        function discription.                                           */
/*                                                                        */
/*        org values of pio_parm                        return value      */
/*        pi_param + 1 <= pi_max_value                  pi_param+1        */
/*        pi_max_value <  pi_param + 1                  0                 */
/* remark : range of output must be 0..(2^k-1) rather                     */
/*          leagal values of pi_max_value are 1,3,4,7,15..ext.            */
#define MBDR_DSP_UTILS_BIN_CYCLIC_INC_M(pi_param, pi_max_value)\
            ((pi_param+1) & (pi_max_value))


/* test selected bit macro.                                      */
/* return 1 if the tested bit is set and 0 if it is reset.       */
#define MBDR_DSP_UTILS_BIT_TEST_M(PI_INPUT_BINARY_PARAMETER, PI_TEST_BIT_NUM)\
                        (((PI_INPUT_BINARY_PARAMETER) >> (PI_TEST_BIT_NUM)) & 0x1 )

/* set selected bit macro                                        */
/* return input parameter after setting its set_bit_num_bit.     */
#define MBDR_DSP_UTILS_BIT_SET_M(PI_INPUT_BINARY_PARAMETER, PI_SET_BIT_NUM)\
                         PI_INPUT_BINARY_PARAMETER  |\
                         (( 100001 & 0x1 )<< (PI_SET_BIT_NUM) )

/* reset selected bit macro                                      */
/* return input parameter after resetting its reset bit_num bit. */
//#define MBDR_DSP_UTILS_BIT_RESET_M(PI_INPUT_BINARY_PARAMETER, PI_RESET_BIT_NUM)\
//       ((0xffffffff ^ (1 << (PI_RESET_BIT_NUM) )) & (PI_INPUT_BINARY_PARAMETER))
#define MBDR_DSP_UTILS_BIT_RESET_M(PI_INPUT_BINARY_PARAMETER, PI_RESET_BIT_NUM)\
       ((~(1<<(PI_RESET_BIT_NUM))) & (PI_INPUT_BINARY_PARAMETER))


/* macro copy lsb bit of pi_new_bit_value to pi_modify_bit_number of . */
/* pi_operand.                                                         */
/* algoritm : 1. reset pi_modify_bit_number of pi_operand.             */
/*            2. or result with lsb value of pi_new_bit_value.         */
#define MBDR_DSP_UTILS_BIT_WRITE_M(pi_operand, pi_modify_bit_number, pi_new_bit_value)\
    pi_operand = ((pi_operand) & (~(1<<(PI_RESET_BIT_NUM)))\
             |\
             (((pi_new_bit_value) & 1) << (pi_modify_bit_number))


/* return div 64k based on shift (2^10=1024, 2^6=64)*/
#define DIV_64K_M(pi_abslt_adrs_long) (pi_abslt_adrs_long <<(10+6))

#define MBDR_DSP_UTILS_ALIGN_BIT_NUM_64BIT_2_32BIT(BIT_64) (BIT_64%32)

#define MBDR_DSP_UTILS_ALIGN_ADRS_64BIT_2_32BIT(BIT_64)    (BIT_64/32)

#define MBDR_DSP_UTILS_GET_NIBBLE_VAL_M(PI_NUMBER, PI_NIBBLE_NUM)\
          (((PI_NUMBER) >>(PI_NIBBLE_NUM*4)) & 0xF )

#define MBDR_DSP_UTILS_GET_PERCENT_VAL_M(pi_parameter, pi_percentage)\
             ((pi_parameter*pi_percentage)/100)

/* returns (pi_min_val <= pi_test_number <= pi_max_val) */
/* use demorgan rule for optimisation                   */
#define MBDR_DSP_UTILS_CHECK_NUMBER_IN_RANGE_M(pi_test_number,\
                                               pi_min_val,\
                                               pi_max_val)\
         (( (pi_test_number < pi_min_val)\
            +\
            (pi_max_val < pi_test_number)) == 0)

#define MBDR_DSP_UTILS_NUMBER_OUT_OF_RANGE_M(pi_test_number, pi_min_val, pi_max_val)\
     !(CHECK_NUMBER_IN_RANGE_M(pi_test_number, pi_min_val, pi_max_val))


#define MBDR_DSP_UTILS_MIN_M(pi_prm_1, pi_prm_2) (pi_prm_1<pi_prm_2)?pi_prm_1:pi_prm_2
#define MBDR_DSP_UTILS_MAX_M(pi_prm_1, pi_prm_2) (pi_prm_1>pi_prm_2)?pi_prm_1:pi_prm_2


#define MBDR_DSP_UTILS_BIN_CYCLIC_DELTA_M(PI_ORG_VALUE, PI_SUBSTRUCTING, PI_MAX_VALUE)\
    ((PI_ORG_VALUE+PI_MAX_VALUE+1-PI_SUBSTRUCTING)&PI_MAX_VALUE)

#define MBDR_DSP_UTILS_BIN_CYCLIC_SUB_DELTA_M(pi_substrhend, pi_substructor, pi_max_power_2)\
    ((pi_substrhend + pi_max_power_2 - pi_substructor) & (pi_max_power_2-1))

#define MBDR_DSP_UTILS_BIN_CYCLIC_ADD_M(pi_adder1, pi_adder2, pi_max_power_2)\
    ((pi_adder1 + pi_adder2 ) & (pi_max_power_2-1))

/* returns 1 if input integer is even number, else return 0. */
#define MBDR_DSP_UTILS_CHECK_NUMBER_EVEN_M(PI_NUMBER) ((PI_NUMBER & 1) ^ 1)

/* returns 1 if input integer is odd number, else return 0. */
#define MBDR_DSP_UTILS_CHECK_NUMBER_ODD_M(PI_NUMBER)   (PI_NUMBER & 1)

/* returnes 1 if and only if PI_FIRST_PARAM = 0 and PI_SECOND_PARAM = 1. */
/* in other case returnes 0.                                             */
#define MBDR_DSP_UTILS_CHECK_PARAMS_LSB_VAL(PI_PARAM_1, PI_PARAM_1_VAL ,\
                             PI_PARAM_2, PI_PARAM_2_VAL)\
    ( (PI_PARAM_1 ^ PI_PARAM_1_VAL ^ 1) & (PI_PARAM_2 ^ PI_PARAM_2_VAL ^ 1) & 1)


/* converts matlab index to C index */
#define  MBDR_DSP_M2C_INDEX_M(PI_MATLAB_INDEX) ((PI_MATLAB_INDEX)-1)


/* converts c index to C matlab index */
#define  MBDR_DSP_C2M_INDEX_M(PI_C_INDEX) ((PI_C_INDEX)+1)

/* converts input sign bit to factor */
/* 0:  1                             */
/* 1: -1                             */
#define MBDR_DSP_UTILS_SIGN_BIT_2_FACTOR_M(PI_SIGN_BIT)\
                             (1-(2*((SHORT)(PI_SIGN_BIT&1))))

/* performs sign function            */
/* returns:   1 0 < PI_NUMBER        */
/*            0 PI_NUMBER = 0        */
/*           -1 PI_NUMBER < 0        */
#define MBDR_DSP_UTILS_SIGN_M(PI_NUMBER)(((PI_NUMBER) > 0) - ((PI_NUMBER) < 0))



/*returns eighth index of input complex number, */
/*           0:       0 <= phase < 0.25 *pi     */
/*           1: 0.25*pi <= phase < 0.5  *pi     */
/*           2: 0.5 *pi <= phase < 0.75 *pi     */
/*           3: 0.75*pi <= phase < 1.0   pi     */
/*           4: 1.0 *pi <= phase < 1.25 *pi     */
/*           5: 1.25*pi <= phase < 1.5  *pi     */
/*           6: 1.5 *pi <= phase < 1.75 *pi     */
/*           7: 1.75*pi <= phase < 2    *pi     */
extern  const CHAR mbdr_dsp_complex_2_circle_eighth_tbl[64];
#define MBDR_DSP_COMPLEX_2_CIRCLE_EIGHTH_M(PI_REAL, PI_IMAGE)\
   mbdr_dsp_complex_2_circle_eighth_tbl[\
                                 1*(abs(PI_REAL) > abs(PI_IMAGE))\
                               + 2*(abs(PI_REAL) < abs(PI_IMAGE))\
                               + 4*((PI_REAL)  > 0)\
                               + 8*((PI_REAL)  < 0)\
                               +16*((PI_IMAGE) > 0)\
                               +32*((PI_IMAGE) < 0)]


/* performs DW swap */
#define  MBDR_DSP_UTILS_SWAP_DW_M(PI_DW0_P,PI_DW1_P, PI_TEMP)\
         PI_TEMP = *(LONG *)PI_DW0_P;\
          *(LONG *)PI_DW0_P =  *(LONG *)PI_DW1_P;\
          *(LONG *)PI_DW1_P =  PI_TEMP


/* compares input parameter with 3 unsigned 5 bit values returns */
/* 0 : none equal                                                */
/* 1 : at least one comparision fits                             */
/* remark values 1,2,3 can be the same */
#define MBDR_DSP_UTILS_FAST_COMPARE_WITH_3_U5BIT_VALUES_M(PI_COMPARE_VALUE,\
                                                         PI_COMPARE_WITH_1,\
                                                         PI_COMPARE_WITH_2,\
                                                         PI_COMPARE_WITH_3)\
     MBDR_DSP_UTILS_BIT_TEST_M(\
     ((1<<(PI_COMPARE_WITH_1))|(1<<(PI_COMPARE_WITH_2))|(1<<(PI_COMPARE_WITH_3))),\
     (PI_COMPARE_VALUE))

/* increment by 1 */
#define MBDR_DSP_INCREMENT_M(PI_NUMBER) ((PI_NUMBER)+1)

/* decrement by 1 */
#define MBDR_DSP_DECREMENT_M(PI_NUMBER) ((PI_NUMBER)-1)

/* returns x^2 */
#define MBDR_DSP_POWER_2_M(PI_X) ((PI_X)*(PI_X))

/* returns x^3 */
#define MBDR_DSP_POWER_3_M(PI_X) ((PI_X)*(PI_X)*(PI_X))

/* returns x^4 */
#define MBDR_DSP_POWER_4_M(PI_DATA) ( MBDR_DSP_POWER_2_M(PI_DATA)\
                                     *MBDR_DSP_POWER_2_M(PI_DATA))

/* returns 4*round_up(x/32) */
#define MBDR_DSP_ROUND_UP_BITS_NUMBER_TO_DW_NUMBER_M(PI_NUMBER)\
           ((PI_NUMBER+MBDR_DSP_32-1)/MBDR_DSP_32)

/* shift right fixed point and round if necessary  */
#define MBDR_DSP_FIX_POINT_SHIFT_RIGHT_AND_ROUND_M(PI_FIXED, PI_RIGHT_SHIFT, PI_ROUND_F)\
            ( (  ( PI_FIXED)\
                +( (PI_ROUND_F) << ((PI_RIGHT_SHIFT)-1)))\
               >>\
               (PI_RIGHT_SHIFT) )

/* sets const memory byte */
#define  MBDR_DSP_SET_CONST_CHAR_MEMORY(PI_IO_CHAR_ADDRESS, PI_VALUE)\
         *((CHAR *)PI_IO_CHAR_ADDRESS) = PI_VALUE


/* returns unsigned nibble from nibble packed array                   */
/*    PI_NIBBLE_ARRAY_P -> nibbles packed array                       */
/*    PI_NIBBLE_INDEX   -  index of inrerested nibble in packed array */
#define MBDR_DSP_GET_UNSIGNED_NIBBLE_FROM_NIBBLE_PACKED_ARRAY_M(PI_NIBBLE_ARRAY_P,\
                                                                PI_NIBBLE_INDEX)\
 MBDR_DSP_UTILS_EXTRACTU_BIT_FEILD_M(\
          *(((UCHAR*)PI_NIBBLE_ARRAY_P)+((PI_NIBBLE_INDEX)/2)),\
           MBDR_DSP_UTILS_BIT_TEST_M((PI_NIBBLE_INDEX), 0)?MBDR_DSP_4:0,\
           MBDR_DSP_4)

/* MBDR_DSP_FAST_IF_ELSEIF_ELSE_ASSIGN_M    */
/* fast imlementation of                    */
/* if(PI_CONDITION_1_QUESTION)              */
/*   output = PI_CONDITION_1_OUTPUT         */
/*   else if(PI_CONDITION_2_QUESTION)       */
/*          output = PI_CONDITION_2_OUTPUT  */
/*        else output = PI_DEFULAT          */
/* fast imlementation of                    */
#define MBDR_DSP_FAST_IF_ELSEIF_ELSE_ASSIGN_M(PI_DEFULAT_OUTPUT,\
                                              PI_CONDITION_1_QUESTION,\
                                              PI_CONDITION_1_OUTPUT,\
                                              PI_CONDITION_2_QUESTION,\
                                              PI_CONDITION_2_OUTPUT)\
    (PI_CONDITION_1_QUESTION)\
    ?PI_CONDITION_1_OUTPUT\
	:((PI_CONDITION_2_QUESTION)?PI_CONDITION_2_OUTPUT:PI_DEFULAT_OUTPUT)


/* MBDR_DSP_UTILS_CLIP_M                                           */
/* clip input value to required range                              */
/* It is user responsibility that PI_MIN_VALUE<=PI_MAX_VALUE       */
#define MBDR_DSP_UTILS_CLIP_M(PI_NUMBER, PI_RANGE_MIN_VALUE, PI_RANGE_MAX_VALUE)\
         max((PI_RANGE_MIN_VALUE), min((PI_NUMBER), (PI_RANGE_MAX_VALUE)))

/* clips input index to [0..((PI_TABLE_SIZE-1)]  */
#define MBDR_DSP_UTILS_CLIP_TABLE_INDEX_M(PI_INDEX, PI_TABLE_SIZE)\
		MBDR_DSP_UTILS_CLIP_M((PI_INDEX), 0, (PI_TABLE_SIZE-1))

#define MBDR_DSP_X_MOD_POW_OF_2_M(PI_NUMBER, PI_POW_N_OF_2_NUM)\
        ((PI_NUMBER) & ((PI_POW_N_OF_2_NUM) - 1))

/* returns minimal cyclic difference between U31                                               */
/* useful for a case of race problems when clocks are not ideally synchronized and application */
/* want to check if relative time difference passed edge which range is [offset_error..2^30-1] */
#define MBDR_DSP_MINIMUM_CYCLIC_DIFFERENCE_U31_M(PI_U31_A, PI_U31_B)\
	     (((PI_U31_A)>(PI_U31_B))\
          ?min(PI_U31_A-PI_U31_B, PI_U31_B+(0x0ffffffff-PI_U31_A)+1)\
          :min(PI_U31_B-PI_U31_A, PI_U31_A+(0x0ffffffff-PI_U31_B)+1))



/* returns minimal value in 1..4 elements vector size */
extern void  mbdr_dsp_vec_s32_4_elements_min(
                        LONG *pi_s32_vec_p,
                        LONG  pi_vec_size,
                        LONG *po_minimal_p);

/* suppouse external device changes 2 following DW in memory */
/* and in each change it toggles sync bit which is located   */
/* in the same place in first DW and second DW               */
/* following routine reads the 2 DW buffer                   */
/* pio_debug_counters_p-> used for sticking tracing          */
/*     start/exit counters are being incrmented upon call/exit  respectively */
/*     in steady state they should be balanced, suppose cleared upon init    */
typedef struct _mbdr_dsp_read_sync_2_dw_debug_counters_t
{
 UCHAR start_count;
 UCHAR exit_count;
 SHORT user_code;
}mbdr_dsp_read_sync_2_dw_debug_counters_t;
extern void mbdr_dsp_read_sync_2_dw(
         volatile LONG  *pi_src_2dw_buf_p,
                  LONG   pi_sync_bit_number,
                  mbdr_dsp_read_sync_2_dw_debug_counters_t 
                        *pio_debug_counters_p,
                  LONG  *po_dst_read_sync_2dw_buf_p);


/* memset loop */
typedef struct
{
  void    *destination_buf_p;
  CHAR     memset_value;
  size_t   byte_size;
}mbdr_dsp_memset_interface_t;
extern void mbdr_dsp_list_memset(
                 mbdr_dsp_memset_interface_t *pi_memset_interface_list_p,
                 SHORT                        pi_memset_list_elements_number);




extern void mbdr_dsp_vec_add_base_to_pointers_list(
                SHORT  pi_base,
                SHORT  pi_list_size,
                CHAR  **pio_pointers_list_pp);


/* sets predecessor & successor bit of each set bit                        */
/* for instance 0x00130021 -> 0x003f8073 & successor bit of each set bit   */
/* input output arrays may be the same                                     */
extern void mbdr_dsp_packed_bits_array_set_single_bit_around_set_bit(
             ULONG  *pi_source_dw_buf_p,
             SHORT   pi_buf_dw_size,
             ULONG  *po_destination_dw_buf_p);


/* sets holes of singles bit */
/* for instance{0x40130521, 0x40000001} -> {0xc0130721, 0x40000001}   */
/* input/output buffers may be the same                               */
extern void mbdr_dsp_packed_bits_array_set_single_bit_holes(
                     ULONG  *pi_source_dw_buf_p,
                     SHORT   pi_buf_dw_size,
                     ULONG  *po_destination_dw_buf_p);


/* clears bits [pi_number_of_used_bits..128K-1)                                 */
/* Inputs:  pi_number_of_used_bits - number of used bits in vector              */
/*                                                                              */
/* Input/Output - pio_vec_bits_p -> bits vector, since memory is not bit access */
/*                                  one DW may need to be read and then partly  */
/*                                  clear                                       */
extern void mbdr_dsp_vec_bits_align_4dw_clean_unused_end_bits_in_last_4dw(
                                         ULONG   pi_number_of_used_bits,
                                         ULONG  *pio_vec_bits_p);

/* function: Shifts left input packed bits vector                           */
/*      Y(k) = X(k+n) of up to 16 bits shift                                */
/* IV.  INPUTS                                                              */
/*      *pi_original_packed_bits_p -> original noise bits                   */
/*                                                                          */
/*       pi_vector_bit_size - 64, 128,...64K                                */
/*                                                                          */
/*       pi_shift_value - [0..16]                                           */
/*                                                                          */
/* V.   OUTPUTS                                                             */
/*      *po_shifted_packed_bits_p -> see function above                     */
/*      note that the function returns a signed version of the vector       */
/*      in case the MSB is 1.                                               */
extern void mbdr_dsp_vec_s16_shift_right_word(
                   SHORT  *pi_original_packed_bits_p,
                   SHORT  pi_vector_bits_number,
				   USHORT pi_shift_value,
                   SHORT  *po_shifted_packed_bits_p);

/* function: Shifts left input packed bits vector                           */
/*      Y(k) = X(k-n) of up to 16 bits shift                                */
/*                                                                          */
/* IV.  INPUTS                                                              */
/*      *pi_original_packed_bits_p -> original noise bits                   */
/*                                                                          */
/*       pi_vector_bit_size - 64, 128,...64K                                */
/*                                                                          */
/*       pi_shift_value - [0..16]                                           */
/*                                                                          */
/* V.   OUTPUTS                                                             */
/*      *po_shifted_packed_bits_p -> see function above                     */
/*      note that the function returns a signed version of the vector       */
/*      in case the MSB is 1.                                               */
extern void mbdr_dsp_vec_s16_shift_left_word(
                   SHORT *pi_original_packed_bits_p,
                   SHORT pi_vector_bits_number,
				   UCHAR pi_shift_value,
                   SHORT *po_shifted_packed_bits_p);

/* Function: the function receives 8k elements array and fins maximum       */
/*           value and index of maximum value                               */
/*                                                                          */
/* Inputs : 1) pi_s16_p                       -> input data vector          */
/*        : 2) pi_buf_elements_number        -   8, 16, 24, .. 8K           */
/*        : 3) po_max_value-> maximum value of the vector                   */
/*        : 4) po_ind_max-> index of maximum value                          */
/*                                                                          */
/* Return : maximum value, index of maximum value                           */
extern void mbdr_dsp_vec_s16_find_ind_max(
						SHORT  *pi_s16_p,
						SHORT  pi_buf_elements_number,
						LONG  *po_max_value_p,
                        SHORT  *po_ind_max_p);

/* Function: the function receives 8k elements array and fins minimum       */
/*           value and index of minimum value                               */
/*                                                                          */
/* Inputs : 1) pi_s16_p                       -> input data vector          */
/*        : 2) pi_buf_elements_number        -   8, 16, 24, .. 8K           */
/*        : 3) po_min_value-> minimum value of the vector                   */
/*        : 4) po_ind_min-> index of minimum value                          */
/*                                                                          */
/* Return : minimum value, index of minimum value                           */
extern void mbdr_dsp_vec_s16_find_ind_min(
						SHORT  *pi_s16_p,
						SHORT  pi_buf_elements_number,
						LONG  *po_min_value_p,
                        SHORT  *po_ind_min_p);

/* II.  FUNCTION                                                            */
/*         receives vector which has x relevant elements and its length is  */
/*         round up to length y. the function sets default value            */
/*         (user defined) in vector indices arr[x]...arr[y-1]               */
/*                                                                          */
/* Inputs:                                                                  */
/*         pio_s16_buf_p -> signed input vector                             */
/*         pi_pad_value -> default value to pad last vector entries         */
/*         pi_buf_actual_elemets_num -> relevant length of input vector     */
/*         pi_buf_elements_num_round_up -> length of vac rounded up         */
/*                                                                          */
/* Output: vector paded with default values in its tail                     */
extern void mbdr_dsp_vec_s16_pad_last_idx(
							SHORT  *pio_s16_buf_p,
							SHORT   pi_pad_value,
							SHORT   pi_buf_actual_elemets_num,
							SHORT   pi_buf_elements_num_round_up);

/* Function: the function receives array of SHORTs, and number of used bits */
/*           the function cleans every unused bit in the array              */
/*           that is- if there are x used bits the function resets bits     */
/*           x+1 till end of array.                                         */
/*                                                                          */
/* Inputs:  pio_s16_vec - vector of SHORTs                                  */
/*          num_of_used_bits                                                */
/*          num_of_short_2_clean - number of shorts (include used bits)     */
/*                                                                          */
/* Input/Output - pio_s16_vec -> vector of SHORTs clean in the tail         */
/*                                                                          */
extern void mbdr_dsp_vec_s16_clean_end_bits(
										SHORT *pio_s16_vec,
                                        SHORT num_of_used_bits,
										SHORT num_of_short_2_clean);

#endif
