Merge pull request #37 in PASDK/pasdk_sr from pasdk_663_shalini to pasdk1_3_master
[processor-sdk/performance-audio-sr.git] / pasrc / test_dsp / io / ioBuff.c
2 #include "ioBuff.h"
3 #include "ioBuff_loc.h"
4 #include "libarch.h"
5 #include <stdint.h>
6 #include <string.h>
8 /******************************************************************************
9 * Implementation of I/O Buffer Management Component
10 ******************************************************************************/
12 #define IOBUF_NUM_MEM_ALLOCS 1
13 #define IOBUFF_INST_ALIGN   3 
15 /*******************************************************************************
16 * API function: ioBuffNumAlloc
17 *    Returns the maximum number of memory allocation requests that ioBuffAlloc() 
18 *    requires.
19 *******************************************************************************/
20 int ioBuffNumAlloc(void)
21 {
22   return (IOBUF_NUM_MEM_ALLOCS);
23 }
25 /*******************************************************************************
26 * API function: ioBuffAlloc
27 *    Returns a table of memory records that describe the size, alignment, type 
28 *    and memory space of all buffers required by this component. 
29 *******************************************************************************/
30 int ioBuffAlloc(lib_mem_rec_t *mem_tbl)
31 {
32   mem_tbl[0].size = sizeof(ioBuffInst_t);
33   mem_tbl[0].alignment = IOBUFF_INST_ALIGN;
34   mem_tbl[0].type = LIB_PMEM_SLOW;
35   mem_tbl[0].base = NULL;
37   return (IOBUFF_NOERR);
38 }
40 /*******************************************************************************
41 * API function: ioBuffCreate
42 *    Create an I/O buffer management instance. 
43 *******************************************************************************/
44 int ioBuffCreate(ioBuffHandle_t *handle, const lib_mem_rec_t *mem_tbl) 
45 {
46   ioBuffInst_t *inst;
48   if(  (mem_tbl[0].size < sizeof(ioBuffInst_t))
49      ||libChkAlign(mem_tbl[0].base, IOBUFF_INST_ALIGN) ) {
50     // to add: check memory type
51     return (IOBUFF_ERR_MEMORY);
52   }
54   inst = (ioBuffInst_t *)mem_tbl[0].base;
55   
56   *handle = (ioBuffHandle_t)inst;
58   return (IOBUFF_NOERR);  
59 }
61 /*******************************************************************************
62 * API function: ioBuffInit
63 *    Initializes the I/O buffer management instance. 
64 *******************************************************************************/
65 int ioBuffInit (ioBuffHandle_t handle, const ioBuffParams_t *params)
66 {
67   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
69   if(params == NULL) {
70     return (IOBUFF_ERR_BAD_PARAMS);
71   }
73   if((params->base == NULL) || (params->nominalDelay >= params->size)) {
74     return (IOBUFF_ERR_BAD_PARAMS);
75   }
77   /* initialize the instance */
78   inst->base  = params->base;  // I/O memory pool base address 
79   inst->size  = params->size;  // I/O memory pool size
80   inst->end   = (void *)((uint_least32_t)inst->base + inst->size);
81   inst->sync  = params->sync;           // synchronous read or synchronous write
82   inst->nom_delay = params->nominalDelay;   // nominal delay for synchronous read/write
84   //inst->rw_wrap_around = 0;
85   inst->status = BUFF_STATUS_NORMAL;
86   inst->read_ptr  = inst->read_complete_ptr  = inst->base;
87   inst->write_ptr = inst->write_complete_ptr = (void *)((uint_least32_t)inst->base + inst->nom_delay);
89 //  memset(inst->base, 0, inst->nom_delay);
91   return (IOBUFF_NOERR);  
92 } /* ioBuffInit */
94 /*******************************************************************************
95 * API function: Return read pointer(s)
96 *******************************************************************************/
97 int ioBuffGetReadPtrs(ioBuffHandle_t handle, size_t mem_size, 
98                       void **ptr1, size_t *size1, void **ptr2, size_t *size2)
99 {
100   uint_least32_t address_end_of_read;
101   void * new_read_ptr;
102   int ret_val;
103   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
105   if(inst->status != BUFF_STATUS_OVERFLOW) {
106     /* check if buffer underflows */
107     if(  (  ((uint_least32_t)inst->write_complete_ptr >= (uint_least32_t)inst->read_ptr)
108           &&(((uint_least32_t)inst->write_complete_ptr - 
109               (uint_least32_t)inst->read_ptr) < mem_size)
110          )
111        ||(  ((uint_least32_t)inst->write_complete_ptr < (uint_least32_t)inst->read_ptr)
112           &&(((uint_least32_t)inst->write_complete_ptr + inst->size - 
113               (uint_least32_t)inst->read_ptr) < mem_size)
114          )
115       ) {
116       /* Buffer underflows */ 
117       inst->status = BUFF_STATUS_UNDERFLOW;
118   
119       if(inst->sync == IOBUff_READ_SYNC) {
120         /*If it's read-synchronized, don't return from here, but still return
121         read pointer(s) calculated after this.  */
122 #if 0        
123         /* reset the delay between read and write_complete pointers */
124         uint_least32_t delay_adjust = inst->nom_delay;
125         if(delay_adjust < mem_size) {
126           delay_adjust = mem_size;
127         }
128         inst->read_ptr = (void *)((uint_least32_t)inst->write_complete_ptr - 
129                                                   delay_adjust);
130         if(inst->read_ptr < inst->base) {
131           inst->read_ptr = (void *)((uint_least32_t)inst->read_ptr + inst->size);
132           //inst->rw_wrap_around = 1;   // set wrap around flag
133         }
134          
135 #endif
136         /* Make a dummy frame and fill it with 0's */
137         new_read_ptr = (void *)((uint_least32_t)inst->write_complete_ptr - mem_size);
138         if(new_read_ptr < inst->base) {
139           new_read_ptr = (void *)((uint_least32_t)new_read_ptr + inst->size);
140           
141           memset(new_read_ptr, 0, mem_size - ((uint_least32_t)inst->write_complete_ptr - (uint_least32_t)inst->base));
142           memset(inst->base, 0, (uint_least32_t)inst->write_complete_ptr - (uint_least32_t)inst->base);
143         }
144         else {
145           memset(new_read_ptr, 0, mem_size);
146         }
147         
148         /* Set read_ptr for calculating returning read pointer(s) below */
149         inst->read_ptr = new_read_ptr;
150          
151         ret_val = IOBUFF_ERR_UNDERFLOW;
152       }
153       else {
154         /* Return here if it underflows but is not read-synchronized. */
155         *ptr1 = NULL; *size1 = 0;
156         *ptr2 = NULL; *size2 = 0;
157         return(IOBUFF_ERR_UNDERFLOW);
158       }
159     }
160     else {
161       inst->status = BUFF_STATUS_NORMAL;
162       ret_val = IOBUFF_NOERR;
163     }
164   } /* if(inst->status != BUFF_STATUS_OVERFLOW) */
165   else {
166     /* already in overflow and remain in overflow untill there is some distance 
167        between read pointer and write pointer */
168     ret_val = IOBUFF_ERR_OVERFLOW;    
169   } 
171   /* return 1 or 2 pointers depending buffer wraps around or not */
172   *ptr1 = inst->read_ptr;  /* starting address to read */
174   /* check if read pointer is going to wrap around during this read */
175   address_end_of_read = (uint_least32_t)inst->read_ptr + mem_size;
176   if(address_end_of_read <= (uint_least32_t)inst->end) {  
177     /* read pointer not going to wrap aound - return only 1 pointer */
178     *size1 = mem_size;
179     *ptr2  = NULL; *size2 = 0;
180     new_read_ptr = (void *)address_end_of_read;
181     if(address_end_of_read == (uint_least32_t)inst->end) {
182       new_read_ptr = inst->base;
183     }
184   }
185   else {  
186     /* read pointer going to wrap around - return 2 pointers */
187     *size1 = (size_t)inst->end - (size_t)inst->read_ptr;
188     *ptr2  = inst->base;
189     *size2 = mem_size - *size1;
190     new_read_ptr = (void *)((uint_least32_t)inst->base + *size2);   
191   }
193   /* update read pointer */
194   inst->read_ptr = new_read_ptr; 
196   return (ret_val);
197 } /* ioBuffGetReadPtrs */
200 /*******************************************************************************
201 * API function: Rewind read pointer by a given amount.
202 *******************************************************************************/
203 int ioBuffRewindReadPtr(ioBuffHandle_t handle, size_t rewind_size)
205   uint_least32_t address_rewind_read;
206   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
208   address_rewind_read = (uint_least32_t)inst->read_ptr - rewind_size;
209   if(address_rewind_read < (uint_least32_t)inst->base) {
210         address_rewind_read = (uint_least32_t)inst->end - ((uint_least32_t)inst->base-address_rewind_read );
211   }
212   inst->read_ptr = (void *)address_rewind_read;
214   return IOBUFF_NOERR;
215 } /* ioBuffRewindReadPtr */
217 /*******************************************************************************
218 * API function: Return write pointer(s)
219 *******************************************************************************/
220 int ioBuffGetWritePtrs(ioBuffHandle_t handle, size_t mem_size, 
221                        void **ptr1, size_t *size1, void **ptr2, size_t *size2)
223   int ret_val;
224   uint_least32_t address_end_of_write;
225   void * new_write_ptr;
226   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
228   /* check if buffer overflows or not */
229   if(inst->status != BUFF_STATUS_UNDERFLOW) {   // this condition may need to be removed!!!
230     if(  (  ((uint_least32_t)inst->read_complete_ptr < (uint_least32_t)inst->write_ptr)
231           &&(((uint_least32_t)inst->read_complete_ptr + inst->size - 
232               (uint_least32_t)inst->write_ptr) < mem_size)
233          )
234        ||(  ((uint_least32_t)inst->read_complete_ptr >= (uint_least32_t)inst->write_ptr)
235           &&(((uint_least32_t)inst->read_complete_ptr - 
236               (uint_least32_t)inst->write_ptr) < mem_size)
237          )
238       ) {
239       /* Buffer overflows */
240       inst->status = BUFF_STATUS_OVERFLOW;
241   
242       if(inst->sync == IOBUFF_WRITE_SYNC){
243         /* If it's write-synchronized, don't return from here. Still return the 
244            write pointer(s) calculated below. */
245         ret_val = IOBUFF_ERR_OVERFLOW;
246       }
247       else {
248         /* Return here if it overflows but is not write-synchronized. */
249         *ptr1 = NULL; *size1 = 0;
250         *ptr2 = NULL; *size2 = 0;
251         return(IOBUFF_ERR_OVERFLOW);
252       }
253     } 
254     else {
255       inst->status = BUFF_STATUS_NORMAL;
256       ret_val = IOBUFF_NOERR;
257     }
258   } 
259   else {
260     /* already in underflow and remain in underflow untill write pointer is 
261        ahead of read pointer */
262     //ret_val = IOBUFF_ERR_UNDERFLOW;
263     ret_val = IOBUFF_NOERR;  // underflow is not an error when getting write pointers
264   }
266   /* return 1 or 2 pointers depending buffer wraps around or not */
267   *ptr1 = inst->write_ptr;  /* starting address to write */
269   /* check if write pointer is going to wrap around during this write */
270   address_end_of_write = (uint_least32_t)inst->write_ptr + mem_size;
271   if(address_end_of_write <= (uint_least32_t)inst->end) {  
272     /* write pointer not going to wrap aound, return only 1 pointer */
273     *size1 = mem_size;
274     *ptr2  = NULL; *size2 = 0;
276     new_write_ptr = (void *)address_end_of_write;
277     if(address_end_of_write == (uint_least32_t)inst->end) {
278       new_write_ptr = inst->base;
279     }
280   }
281   else {  
282     /* write pointer going to wrap around, return 2 pointers */
283     *size1 = (size_t)inst->end - (size_t)inst->write_ptr;
284     *ptr2  = inst->base;
285     *size2 = mem_size - *size1;
286     new_write_ptr = (void *)((uint_least32_t)inst->base + *size2);
287   }
289   /* update write pointer */
290   inst->write_ptr = new_write_ptr;
292   return (ret_val);
293 } /* ioBuffGetWritePtrs */
295 /*******************************************************************************
296 * API function: Mark read completion
297 *******************************************************************************/
298 int ioBuffReadComplete(ioBuffHandle_t handle, void *read_begin, size_t read_size)
300   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
302   inst->read_complete_ptr = (void *)((uint_least32_t)read_begin+read_size);
303   if(inst->read_complete_ptr >= inst->end) {
304     inst->read_complete_ptr = (void *) ((uint_least32_t)inst->read_complete_ptr 
305                                         - inst->size);
306     //inst->rw_wrap_around ^= 1;   // toggle wrap around flag
307   }
309   return (IOBUFF_NOERR);
310 }  /* ioBuffReadComplete */
312 /*******************************************************************************
313 * API function: Mark write completion
314 *******************************************************************************/
315 int ioBuffWriteComplete(ioBuffHandle_t handle, void *write_begin, size_t write_size)
317   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
319   inst->write_complete_ptr = (void *)((uint_least32_t)write_begin+write_size);
320   if(inst->write_complete_ptr >= inst->end) {
321     inst->write_complete_ptr = (void *)((uint_least32_t)inst->write_complete_ptr 
322                                         - inst->size);
323     //inst->rw_wrap_around ^= 1;   // toggle wrap around flag
324   }
326   return (IOBUFF_NOERR);
327 }  /* ioBuffWriteComplete */
330 int ioBuffGetInfo(ioBuffHandle_t handle, ioBuffInfo_t *info)
332   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
334   info->base  = inst->base;
335   info->read  = inst->read_ptr;
336   info->write = inst->write_ptr;
337   info->size  = inst->size;
339   return (IOBUFF_NOERR);
340 } /* ioBuffGetInfo */
343 void * ioBuffWrapPointer(ioBuffHandle_t handle, void *pPtr)
345   uint_least32_t ptr_temp;
346   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
348   ptr_temp = (uint_least32_t)pPtr;
349   if(ptr_temp >= (uint_least32_t)inst->end) {
350     ptr_temp = (uint_least32_t)inst->base + ptr_temp - (uint_least32_t)inst->end;
351   }
353   return ((void *)ptr_temp);
354 } /* ioBuffWrapPointer */
356 #if 0
357 int ioBuffWrapPointer(ioBuffHandle_t handle, void **pPtr)
359   uint_least32_t ptr_temp;
360   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
362   ptr_temp = (uint_least32_t)*pPtr;
363   if(ptr_temp >= (uint_least32_t)inst->end) {
364     ptr_temp = (uint_least32_t)inst->base + ptr_temp - (uint_least32_t)inst->end;
365   }
367   *pPtr = (void *)ptr_temp;
369   return (IOBUFF_NOERR);
370 } /* ioBuffWrapPointer */
371 #endif
373 int ioBuffAdjustDelay(ioBuffHandle_t handle, size_t delay)
375     size_t temp;
376     ioBuffInst_t *inst = (ioBuffInst_t *)handle;
378     if( (size_t)inst->write_complete_ptr >= ((size_t)inst->base+delay) ) {
379         inst->read_ptr = inst->read_complete_ptr = (void *)((size_t)inst->write_complete_ptr - delay);
380         //inst->rw_wrap_around = 0;
381     }
382     else {
383         temp = delay - ((size_t)inst->write_complete_ptr - (size_t)inst->base);
384         inst->read_ptr = inst->read_complete_ptr = (void *)((size_t)inst->end - temp);
385         //inst->rw_wrap_around = 1;
386     }
388     inst->nom_delay = delay;
390     return (IOBUFF_NOERR);
391 } /* ioBuffAdjustDelay */
393 /* Nothing past this point */