/*                                                                          */


#include "windef.h"
#include "string.h"
#include "mbdr_dsp_utils.h"
#include "mbdr_dsp_cyclic_buffer.h"


extern USHORT mbdr_dsp_cyclic_buf_dummy;
USHORT mbdr_dsp_cyclic_buf_dummy;
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)
{/* mbdr_dsp_cyclic_buf_standat_c_memcpy */
  mbdr_dsp_cyclic_buf_dummy = pi_dummy_memcpy_code;
  return(memcpy(dst_p, src_p, (size_t)pi_buf_data_size));
}/* mbdr_dsp_cyclic_buf_standat_c_memcpy */

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)
{/* mbdr_dsp_cyclic_buf_config */

 memset((void *)po_buffer_header_area_p, 0, sizeof(mbdr_dsp_cyclic_buf_hdr_t));
 po_buffer_header_area_p->entries_number      = pi_entries_number;
 po_buffer_header_area_p->entry_byte_size     = pi_entry_byte_size;
 po_buffer_header_area_p->buffer_base_p       = (UCHAR*) pi_buffer_data_area_p;
 po_buffer_header_area_p->write_memcpy_proc_p = 
             (void *(*)(void *, const void *, USHORT, USHORT))&memcpy;
 //po_buffer_header_area_p->write_memcpy_proc_p = 
 //  (void *(*)(void *, const void *, USHORT, USHORT))
 //   &mbdr_dsp_cyclic_buf_standat_c_memcpy;

 
 po_buffer_header_area_p->synchronized_access_free_entries = pi_entries_number -1;
 po_buffer_header_area_p->synchronized_access_occupied_entries = 0;

}/* mbdr_dsp_cyclic_buf_config */

void mbdr_dsp_cyclic_buf_write(void *pi_data_p,
                               mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p)
{/* mbdr_dsp_cyclic_buf_write */

 /* perform copy */
 pio_cyclic_buffer_hdr_p->write_memcpy_proc_p
 ((void *)MBDR_DSP_CYCLIC_BUFFER_GET_WRITE_PTR_M(pio_cyclic_buffer_hdr_p),
        (const void *)pi_data_p,
        (size_t)pio_cyclic_buffer_hdr_p->entry_byte_size,
         pio_cyclic_buffer_hdr_p->data_memcpy_code);


 /* increment write index */
 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++;

}/* mbdr_dsp_cyclic_buf_write */

void mbdr_dsp_cyclic_buf_read(void  *po_read_data_p,
                                 mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p)
{/* mbdr_dsp_cyclic_buf_read */

 /* perform copy */
 mbdr_dsp_utils_memcpy_dw_by_dw(po_read_data_p,
        MBDR_DSP_CYCLIC_BUFFER_GET_READ_PTR_M(pio_cyclic_buffer_hdr_p),
        pio_cyclic_buffer_hdr_p->entry_byte_size);

 /* increment read index */
 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--;

}/* mbdr_dsp_cyclic_buf_read */

SHORT mbdr_dsp_cyclic_buf_add(
                   SHORT   pi_index,
				   SHORT   pi_add_value,
                   mbdr_dsp_cyclic_buf_hdr_t  *pi_cyclic_buffer_hdr_p)
{
  if((pi_index+pi_add_value)>=pi_cyclic_buffer_hdr_p->entries_number)
    return(-(pi_cyclic_buffer_hdr_p->entries_number - pi_index) + pi_add_value);
  else 
    return( pi_index+pi_add_value);
}

SHORT mbdr_dsp_cyclic_buffer_get_room(mbdr_dsp_cyclic_buf_hdr_t  *pi_cyclic_buffer_hdr_p)
{
 register SHORT write_index,
                read_index,
                return_value; 

 /* read into local to protect against volatile run time update */
 write_index = pi_cyclic_buffer_hdr_p->write_index;
 read_index  = pi_cyclic_buffer_hdr_p->read_index;

 return_value = 
            -1
            -write_index
            +read_index;
 
 return_value = (read_index <= write_index) ? 
                (return_value + pi_cyclic_buffer_hdr_p->entries_number) 
               : return_value;

 return(return_value);

}

/* increment read index of cyclic buffer */
void mbdr_dsp_cyclic_buf_increment_read_index(
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p)
{/* mbdr_dsp_cyclic_buf_increment_read_index */

 /* increment read index */
// 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--;
 MBDR_DSP_CYCLIC_BUF_INCREMENT_READ_INDEX_M(pio_cyclic_buffer_hdr_p);

}/* mbdr_dsp_cyclic_buf_increment_read_index */

/* increment write index of cyclic buffer */
void mbdr_dsp_cyclic_buf_increment_write_index(
                   mbdr_dsp_cyclic_buf_hdr_t  *pio_cyclic_buffer_hdr_p)
{/* mbdr_dsp_cyclic_buf_increment_write_index */

 /* increment write index */
// 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++;
 MBDR_DSP_CYCLIC_BUF_INCREMENT_WRITE_INDEX_M(pio_cyclic_buffer_hdr_p);

}/* mbdr_dsp_cyclic_buf_increment_write_index */

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)
{/* mbdr_dsp_cyclic_buf_increment_read_index_by_given_value */

// 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;
  MBDR_DSP_CYCLIC_BUF_INCREMENT_READ_INDEX_BY_GIVEN_VALUE_M(pi_increment_value,
                                                            pio_cyclic_buffer_hdr_p);

}/* mbdr_dsp_cyclic_buf_increment_read_index_by_given_value */

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)
{/* mbdr_dsp_cyclic_buf_increment_write_index_by_given_value */

// 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;
 MBDR_DSP_CYCLIC_BUF_INCREMENT_WRITE_INDEX_BY_GIVEN_VALUE_M(pi_increment_value,
                                                           pio_cyclic_buffer_hdr_p);

}/* mbdr_dsp_cyclic_buf_increment_write_index_by_given_value */

SHORT mbdr_dsp_cyclic_buffer_get_occupied_entries(
                   mbdr_dsp_cyclic_buf_hdr_t  *pi_cyclic_buffer_hdr_p)
{/* mbdr_dsp_cyclic_buffer_get_occupied_entries */

   return( pi_cyclic_buffer_hdr_p->entries_number
          -1
          -mbdr_dsp_cyclic_buffer_get_room(pi_cyclic_buffer_hdr_p));

}/* mbdr_dsp_cyclic_buffer_get_occupied_entries */

/* get N items from cyclic buffer */
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)
{/* mbdr_dsp_cyclic_buf_read_n_items */

  LONG   first_delivery_byte_size, second_delivery_byte_size,
         first_read_byte_offset;
  LONG   cyclic_buffer_byte_size, total_delivery_byte_size;

  cyclic_buffer_byte_size  =  
              pio_cyclic_buffer_hdr_p->entry_byte_size
             *pio_cyclic_buffer_hdr_p->entries_number;
  first_read_byte_offset =
              pio_cyclic_buffer_hdr_p->entry_byte_size
	         *pio_cyclic_buffer_hdr_p->read_index;
  total_delivery_byte_size  = 
              pi_items_number
             *pio_cyclic_buffer_hdr_p->entry_byte_size;
  first_delivery_byte_size = 
     MBDR_DSP_UTILS_MIN_M(
            total_delivery_byte_size,
           (cyclic_buffer_byte_size - first_read_byte_offset) );
  second_delivery_byte_size = total_delivery_byte_size
                             -first_delivery_byte_size;

  /* performs first memcpy */
  memcpy(
    po_read_data_buf_p,
   (const void *)MBDR_DSP_CYCLIC_BUFFER_GET_READ_PTR_M(pio_cyclic_buffer_hdr_p),
   (size_t)first_delivery_byte_size);

  /* performs second memcpy, if needed */
  if(second_delivery_byte_size)
    memcpy((void *)(((CHAR *)po_read_data_buf_p)+first_delivery_byte_size),
           (const void *)pio_cyclic_buffer_hdr_p->buffer_base_p,
           (size_t)second_delivery_byte_size);

  /* cyclic advance of write index */
  MBDR_DSP_UTILS_CYC_ADD_M(pio_cyclic_buffer_hdr_p->read_index,
                           pi_items_number, 
                           0, 
                           (pio_cyclic_buffer_hdr_p->entries_number-1));

  /* update _free & _occupied fields */
  pio_cyclic_buffer_hdr_p->synchronized_access_free_entries += pi_items_number;
  pio_cyclic_buffer_hdr_p->synchronized_access_occupied_entries -= pi_items_number;

}/* mbdr_dsp_cyclic_buf_read_n_items */

/* writes N items into cyclic buffer */
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)
{/* mbdr_dsp_cyclic_buf_write_n_items */

  LONG   first_delivery_byte_size, second_delivery_byte_size,
         fill_from_start_byte_size;
  LONG   cyclic_buffer_byte_size, total_delivery_byte_size;

  cyclic_buffer_byte_size  =  
              pio_cyclic_buffer_hdr_p->entry_byte_size
             *pio_cyclic_buffer_hdr_p->entries_number;
  fill_from_start_byte_size =
              pio_cyclic_buffer_hdr_p->entry_byte_size
	         *pio_cyclic_buffer_hdr_p->write_index;
  total_delivery_byte_size  = 
              pi_items_number
             *pio_cyclic_buffer_hdr_p->entry_byte_size;
  first_delivery_byte_size = 
     MBDR_DSP_UTILS_MIN_M(
            total_delivery_byte_size,
           (cyclic_buffer_byte_size - fill_from_start_byte_size) );
  second_delivery_byte_size = total_delivery_byte_size
                             -first_delivery_byte_size;

  /* performs first memcpy */
  pio_cyclic_buffer_hdr_p->write_memcpy_proc_p
  ((void *)MBDR_DSP_CYCLIC_BUFFER_GET_WRITE_PTR_M(pio_cyclic_buffer_hdr_p),
   (const void *)pi_write_data_buf_p,
    (size_t)first_delivery_byte_size,
    pio_cyclic_buffer_hdr_p->data_memcpy_code);

  /* performs second memcpy, if needed */
  if(second_delivery_byte_size)
    pio_cyclic_buffer_hdr_p->write_memcpy_proc_p
      ((void *) pio_cyclic_buffer_hdr_p->buffer_base_p,
      (const void *)(((CHAR *)pi_write_data_buf_p)+first_delivery_byte_size),
      (size_t)second_delivery_byte_size,
      pio_cyclic_buffer_hdr_p->data_memcpy_code);


  /* cyclic advance of write index */
  MBDR_DSP_UTILS_CYC_ADD_M(pio_cyclic_buffer_hdr_p->write_index,
                           pi_items_number, 
                           0, 
                           (pio_cyclic_buffer_hdr_p->entries_number-1));

  /* update _free & _occupied fields */
  pio_cyclic_buffer_hdr_p->synchronized_access_free_entries -= pi_items_number;
  pio_cyclic_buffer_hdr_p->synchronized_access_occupied_entries += pi_items_number;

}/* mbdr_dsp_cyclic_buf_write_n_items */

void  mbdr_dsp_cyclic_buffer_config_write_data_proc_p
     (void* (*pi_write_data_memcpy_proc_p)(void *, const void *, USHORT, USHORT),
     mbdr_dsp_cyclic_buf_hdr_t  *po_cyclic_buffer_hdr_p)
{
  po_cyclic_buffer_hdr_p->write_memcpy_proc_p = pi_write_data_memcpy_proc_p;
}


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)
{/* mbdr_dsp_cyclic_buf_read_n_dw_and_split */

 SHORT  i;
 LONG  *cyclic_buf_base_dw_p, next_read_dw_index;
 LONG  *next_read_2dw_p;
 LONG   next_read_even_dw, next_read_odd_dw;



 next_read_dw_index   = pio_cyclic_buffer_hdr_p->read_index;
 cyclic_buf_base_dw_p = (LONG *)
                        pio_cyclic_buffer_hdr_p->buffer_base_p;
 next_read_2dw_p      = &cyclic_buf_base_dw_p[next_read_dw_index];

 for(i=0; i<pi_read_dw_number/2; i++)
 {/* for */
   
    next_read_even_dw    = next_read_2dw_p[0];
    next_read_odd_dw     = next_read_2dw_p[1];
    MBDR_DSP_UTILS_CYC_ADD_M(next_read_dw_index, 
                          2, 
                          0, 
                          (pio_cyclic_buffer_hdr_p->entries_number-1));
    next_read_2dw_p      = &cyclic_buf_base_dw_p[next_read_dw_index];

    /* update output even buffer */ 
    *po_read_even_index_buf_p++ = next_read_even_dw;

    /* update output odd elements buffer */ 
    *po_read_odd_index_buf_p++  = next_read_odd_dw;

 }/* for */

  /* advance queue read index */
  mbdr_dsp_cyclic_buf_increment_read_index_by_given_value(
                                                 pi_read_dw_number,
                                                 pio_cyclic_buffer_hdr_p);

}/* mbdr_dsp_cyclic_buf_read_n_dw_and_split */

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)


{/* mbdr_dsp_cyclic_buf_get_relative_pointer */

  SHORT required_element_index;

  required_element_index = pi_relative_element_index;
  MBDR_DSP_UTILS_CYC_ADD_M(required_element_index,
                           pi_gap, 
                           0, 
                           (pi_cyclic_buffer_hdr_p->entries_number-1));
  
  return(MBDR_DSP_CYCLIC_BUFFER_GET_ELEMENT_PTR_M(
                           pi_cyclic_buffer_hdr_p,
                           required_element_index));
  
  

}/* mbdr_dsp_cyclic_buf_get_relative_pointer */



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  */
void mbdr_dsp_cyclic_buf_config_struct(
      mbdr_dsp_cyclic_buf_config_io_params_t *pio_cyclic_buf_config_io_params_p)
{/* mbdr_dsp_cyclic_buf_config_struct */

  mbdr_dsp_cyclic_buf_config(
                     pio_cyclic_buf_config_io_params_p->pi_entries_number,
                     pio_cyclic_buf_config_io_params_p->pi_entry_byte_size,
                     pio_cyclic_buf_config_io_params_p->pi_buffer_data_area_p,
                     pio_cyclic_buf_config_io_params_p->po_buffer_header_area_p);

}/* mbdr_dsp_cyclic_buf_config_struct */
