Merge branch 'dev_pasdk_frank_pasdk516AsotRefactoring' into dev_pasdk_pasdk29Integration
[processor-sdk/performance-audio-sr.git] / pasdk / 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 below.  */
122         /* reset the delay between read and write_complete pointers */
123         uint_least32_t delay_adjust = inst->nom_delay;
124         if(delay_adjust < mem_size) {
125           delay_adjust = mem_size;
126         }
127         inst->read_ptr = (void *)((uint_least32_t)inst->write_complete_ptr - 
128                                                   delay_adjust);
129         if(inst->read_ptr < inst->base) {
130           inst->read_ptr = (void *)((uint_least32_t)inst->read_ptr + inst->size);
131           //inst->rw_wrap_around = 1;   // set wrap around flag
132         }
133          
134         ret_val = IOBUFF_ERR_UNDERFLOW;
135       }
136       else {
137         /* Return here if it underflows but is not read-synchronized. */
138         *ptr1 = NULL; *size1 = 0;
139         *ptr2 = NULL; *size2 = 0;
140         return(IOBUFF_ERR_UNDERFLOW);
141       }
142     }
143     else {
144       inst->status = BUFF_STATUS_NORMAL;
145       ret_val = IOBUFF_NOERR;
146     }
147   } /* if(inst->status != BUFF_STATUS_OVERFLOW) */
148   else {
149     /* already in overflow and remain in overflow untill there is some distance 
150        between read pointer and write pointer */
151     ret_val = IOBUFF_ERR_OVERFLOW;    
152   } 
154   /* return 1 or 2 pointers depending buffer wraps around or not */
155   *ptr1 = inst->read_ptr;  /* starting address to read */
157   /* check if read pointer is going to wrap around during this read */
158   address_end_of_read = (uint_least32_t)inst->read_ptr + mem_size;
159   if(address_end_of_read <= (uint_least32_t)inst->end) {  
160     /* read pointer not going to wrap aound - return only 1 pointer */
161     *size1 = mem_size;
162     *ptr2  = NULL; *size2 = 0;
163     new_read_ptr = (void *)address_end_of_read;
164     if(address_end_of_read == (uint_least32_t)inst->end) {
165       new_read_ptr = inst->base;
166     }
167   }
168   else {  
169     /* read pointer going to wrap around - return 2 pointers */
170     *size1 = (size_t)inst->end - (size_t)inst->read_ptr;
171     *ptr2  = inst->base;
172     *size2 = mem_size - *size1;
173     new_read_ptr = (void *)((uint_least32_t)inst->base + *size2);   
174   }
176   /* update read pointer */
177   inst->read_ptr = new_read_ptr; 
179   return (ret_val);
180 } /* ioBuffGetReadPtrs */
183 /*******************************************************************************
184 * API function: Rewind read pointer by a given amount.
185 *******************************************************************************/
186 int ioBuffRewindReadPtr(ioBuffHandle_t handle, size_t rewind_size)
188   uint_least32_t address_rewind_read;
189   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
191   address_rewind_read = (uint_least32_t)inst->read_ptr - rewind_size;
192   if(address_rewind_read < (uint_least32_t)inst->base) {
193         address_rewind_read = (uint_least32_t)inst->end - ((uint_least32_t)inst->base-address_rewind_read );
194   }
195   inst->read_ptr = (void *)address_rewind_read;
197   return IOBUFF_NOERR;
198 } /* ioBuffRewindReadPtr */
200 /*******************************************************************************
201 * API function: Return write pointer(s)
202 *******************************************************************************/
203 int ioBuffGetWritePtrs(ioBuffHandle_t handle, size_t mem_size, 
204                        void **ptr1, size_t *size1, void **ptr2, size_t *size2)
206   int ret_val;
207   uint_least32_t address_end_of_write;
208   void * new_write_ptr;
209   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
211   /* check if buffer overflows or not */
212   if(inst->status != BUFF_STATUS_UNDERFLOW) {   // this condition may need to be removed!!!
213     if(  (  ((uint_least32_t)inst->read_complete_ptr < (uint_least32_t)inst->write_ptr)
214           &&(((uint_least32_t)inst->read_complete_ptr + inst->size - 
215               (uint_least32_t)inst->write_ptr) < mem_size)
216          )
217        ||(  ((uint_least32_t)inst->read_complete_ptr >= (uint_least32_t)inst->write_ptr)
218           &&(((uint_least32_t)inst->read_complete_ptr - 
219               (uint_least32_t)inst->write_ptr) < mem_size)
220          )
221       ) {
222       /* Buffer overflows */
223       inst->status = BUFF_STATUS_OVERFLOW;
224   
225       if(inst->sync == IOBUFF_WRITE_SYNC){
226         /* If it's write-synchronized, don't return from here. Still return the 
227            write pointer(s) calculated below. */
228         ret_val = IOBUFF_ERR_OVERFLOW;
229       }
230       else {
231         /* Return here if it overflows but is not write-synchronized. */
232         *ptr1 = NULL; *size1 = 0;
233         *ptr2 = NULL; *size2 = 0;
234         return(IOBUFF_ERR_OVERFLOW);
235       }
236     } 
237     else {
238       inst->status = BUFF_STATUS_NORMAL;
239       ret_val = IOBUFF_NOERR;
240     }
241   } 
242   else {
243     /* already in underflow and remain in underflow untill write pointer is 
244        ahead of read pointer */
245     //ret_val = IOBUFF_ERR_UNDERFLOW;
246     ret_val = IOBUFF_NOERR;  // underflow is not an error when getting write pointers
247   }
249   /* return 1 or 2 pointers depending buffer wraps around or not */
250   *ptr1 = inst->write_ptr;  /* starting address to write */
252   /* check if write pointer is going to wrap around during this write */
253   address_end_of_write = (uint_least32_t)inst->write_ptr + mem_size;
254   if(address_end_of_write <= (uint_least32_t)inst->end) {  
255     /* write pointer not going to wrap aound, return only 1 pointer */
256     *size1 = mem_size;
257     *ptr2  = NULL; *size2 = 0;
259     new_write_ptr = (void *)address_end_of_write;
260     if(address_end_of_write == (uint_least32_t)inst->end) {
261       new_write_ptr = inst->base;
262     }
263   }
264   else {  
265     /* write pointer going to wrap around, return 2 pointers */
266     *size1 = (size_t)inst->end - (size_t)inst->write_ptr;
267     *ptr2  = inst->base;
268     *size2 = mem_size - *size1;
269     new_write_ptr = (void *)((uint_least32_t)inst->base + *size2);
270   }
272   /* update write pointer */
273   inst->write_ptr = new_write_ptr;
275   return (ret_val);
276 } /* ioBuffGetWritePtrs */
278 /*******************************************************************************
279 * API function: Mark read completion
280 *******************************************************************************/
281 int ioBuffReadComplete(ioBuffHandle_t handle, void *read_begin, size_t read_size)
283   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
285   inst->read_complete_ptr = (void *)((uint_least32_t)read_begin+read_size);
286   if(inst->read_complete_ptr >= inst->end) {
287     inst->read_complete_ptr = (void *) ((uint_least32_t)inst->read_complete_ptr 
288                                         - inst->size);
289     //inst->rw_wrap_around ^= 1;   // toggle wrap around flag
290   }
292   return (IOBUFF_NOERR);
293 }  /* ioBuffReadComplete */
295 /*******************************************************************************
296 * API function: Mark write completion
297 *******************************************************************************/
298 int ioBuffWriteComplete(ioBuffHandle_t handle, void *write_begin, size_t write_size)
300   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
302   inst->write_complete_ptr = (void *)((uint_least32_t)write_begin+write_size);
303   if(inst->write_complete_ptr >= inst->end) {
304     inst->write_complete_ptr = (void *)((uint_least32_t)inst->write_complete_ptr 
305                                         - inst->size);
306     //inst->rw_wrap_around ^= 1;   // toggle wrap around flag
307   }
309   return (IOBUFF_NOERR);
310 }  /* ioBuffWriteComplete */
313 int ioBuffGetInfo(ioBuffHandle_t handle, ioBuffInfo_t *info)
315   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
317   info->base  = inst->base;
318   info->read  = inst->read_ptr;
319   info->write = inst->write_ptr;
320   info->size  = inst->size;
322   return (IOBUFF_NOERR);
323 } /* ioBuffGetInfo */
326 void * ioBuffWrapPointer(ioBuffHandle_t handle, void *pPtr)
328   uint_least32_t ptr_temp;
329   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
331   ptr_temp = (uint_least32_t)pPtr;
332   if(ptr_temp >= (uint_least32_t)inst->end) {
333     ptr_temp = (uint_least32_t)inst->base + ptr_temp - (uint_least32_t)inst->end;
334   }
336   return ((void *)ptr_temp);
337 } /* ioBuffWrapPointer */
339 #if 0
340 int ioBuffWrapPointer(ioBuffHandle_t handle, void **pPtr)
342   uint_least32_t ptr_temp;
343   ioBuffInst_t *inst = (ioBuffInst_t *)handle;
345   ptr_temp = (uint_least32_t)*pPtr;
346   if(ptr_temp >= (uint_least32_t)inst->end) {
347     ptr_temp = (uint_least32_t)inst->base + ptr_temp - (uint_least32_t)inst->end;
348   }
350   *pPtr = (void *)ptr_temp;
352   return (IOBUFF_NOERR);
353 } /* ioBuffWrapPointer */
354 #endif
356 int ioBuffAdjustDelay(ioBuffHandle_t handle, size_t delay)
358     size_t temp;
359     ioBuffInst_t *inst = (ioBuffInst_t *)handle;
361     if( (size_t)inst->write_complete_ptr >= ((size_t)inst->base+delay) ) {
362         inst->read_ptr = inst->read_complete_ptr = (void *)((size_t)inst->write_complete_ptr - delay);
363         //inst->rw_wrap_around = 0;
364     }
365     else {
366         temp = delay - ((size_t)inst->write_complete_ptr - (size_t)inst->base);
367         inst->read_ptr = inst->read_complete_ptr = (void *)((size_t)inst->end - temp);
368         //inst->rw_wrap_around = 1;
369     }
371     inst->nom_delay = delay;
373     return (IOBUFF_NOERR);
374 } /* ioBuffAdjustDelay */
376 /* Nothing past this point */