Skip to content

Commit c29b764

Browse files
committed
simplify _ff_correct_read_index()
1 parent 248025b commit c29b764

File tree

1 file changed

+62
-45
lines changed

1 file changed

+62
-45
lines changed

src/common/tusb_fifo.c

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,44 @@ static void _ff_pull_n(tu_fifo_t* f, void* app_buf, uint16_t n, uint16_t rel, tu
314314
}
315315

316316
//--------------------------------------------------------------------+
317-
// Index (free-running and real buffer pointer)
317+
// Helper
318+
//--------------------------------------------------------------------+
319+
320+
// return only the index difference and as such can be used to determine an overflow i.e overflowable count
321+
TU_ATTR_ALWAYS_INLINE static inline
322+
uint16_t _ff_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx)
323+
{
324+
// In case we have non-power of two depth we need a further modification
325+
if (wr_idx >= rd_idx)
326+
{
327+
return (uint16_t) (wr_idx - rd_idx);
328+
} else
329+
{
330+
return (uint16_t) (2*depth - (rd_idx - wr_idx));
331+
}
332+
}
333+
334+
// BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS"
335+
// Only one overflow is allowed for this function to work e.g. if depth = 100, you must not
336+
// write more than 2*depth-1 items in one rush without updating write pointer. Otherwise
337+
// write pointer wraps and you pointer states are messed up. This can only happen if you
338+
// use DMAs, write functions do not allow such an error.
339+
TU_ATTR_ALWAYS_INLINE static inline
340+
bool _ff_overflowed(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx)
341+
{
342+
return _ff_count(depth, wr_idx, rd_idx) > depth;
343+
}
344+
345+
// return remaining slot in fifo
346+
TU_ATTR_ALWAYS_INLINE static inline
347+
uint16_t _ff_remaining(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx)
348+
{
349+
uint16_t const count = _ff_count(depth, wr_idx, rd_idx);
350+
return (depth > count) ? (depth - count) : 0;
351+
}
352+
353+
//--------------------------------------------------------------------+
354+
// Index Helper
318355
//--------------------------------------------------------------------+
319356

320357
// Advance an absolute index
@@ -334,6 +371,7 @@ static uint16_t advance_index(uint16_t depth, uint16_t idx, uint16_t offset)
334371
return new_idx;
335372
}
336373

374+
#if 0 // not used but
337375
// Backward an absolute index
338376
static uint16_t backward_index(uint16_t depth, uint16_t idx, uint16_t offset)
339377
{
@@ -349,6 +387,7 @@ static uint16_t backward_index(uint16_t depth, uint16_t idx, uint16_t offset)
349387

350388
return new_idx;
351389
}
390+
#endif
352391

353392
// index to pointer, simply an modulo with minus.
354393
TU_ATTR_ALWAYS_INLINE static inline
@@ -359,45 +398,24 @@ uint16_t idx2ptr(uint16_t depth, uint16_t idx)
359398
return idx;
360399
}
361400

362-
// return only the index difference and as such can be used to determine an overflow i.e overflowable count
401+
// Works on local copies of w
402+
// When an overwritable fifo is overflowed, rd_idx will be re-index so that it forms
403+
// an full fifo i.e _ff_count() = depth
363404
TU_ATTR_ALWAYS_INLINE static inline
364-
uint16_t _ff_count(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx)
405+
uint16_t _ff_correct_read_index(tu_fifo_t* f, uint16_t wr_idx)
365406
{
366-
// In case we have non-power of two depth we need a further modification
367-
if (wr_idx >= rd_idx)
407+
uint16_t rd_idx;
408+
if ( wr_idx >= f->depth )
368409
{
369-
return (uint16_t) (wr_idx - rd_idx);
370-
} else
410+
rd_idx = wr_idx - f->depth;
411+
}else
371412
{
372-
return (uint16_t) (2*depth - (rd_idx - wr_idx));
413+
rd_idx = wr_idx + f->depth;
373414
}
374-
}
375415

376-
// BE AWARE - THIS FUNCTION MIGHT NOT GIVE A CORRECT ANSWERE IN CASE WRITE POINTER "OVERFLOWS"
377-
// Only one overflow is allowed for this function to work e.g. if depth = 100, you must not
378-
// write more than 2*depth-1 items in one rush without updating write pointer. Otherwise
379-
// write pointer wraps and you pointer states are messed up. This can only happen if you
380-
// use DMAs, write functions do not allow such an error.
381-
TU_ATTR_ALWAYS_INLINE static inline
382-
bool _ff_overflowed(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx)
383-
{
384-
return _ff_count(depth, wr_idx, rd_idx) > depth;
385-
}
416+
f->rd_idx = rd_idx;
386417

387-
// return remaining slot in fifo
388-
TU_ATTR_ALWAYS_INLINE static inline
389-
uint16_t _ff_remaining(uint16_t depth, uint16_t wr_idx, uint16_t rd_idx)
390-
{
391-
uint16_t const count = _ff_count(depth, wr_idx, rd_idx);
392-
return (depth > count) ? (depth - count) : 0;
393-
}
394-
395-
// Works on local copies of w
396-
// For more details see _tu_fifo_overflow()!
397-
TU_ATTR_ALWAYS_INLINE static inline
398-
void _tu_fifo_correct_read_pointer(tu_fifo_t* f, uint16_t wr_idx)
399-
{
400-
f->rd_idx = backward_index(f->depth, wr_idx, f->depth);
418+
return rd_idx;
401419
}
402420

403421
// Works on local copies of w and r
@@ -407,14 +425,14 @@ static bool _tu_fifo_peek(tu_fifo_t* f, void * p_buffer, uint16_t wr_idx, uint16
407425
uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx);
408426

409427
// Check overflow and correct if required
410-
if (cnt > f->depth)
428+
if ( cnt > f->depth )
411429
{
412-
_tu_fifo_correct_read_pointer(f, wr_idx);
430+
rd_idx = _ff_correct_read_index(f, wr_idx);
413431
cnt = f->depth;
414432
}
415433

416434
// Skip beginning of buffer
417-
if (cnt == 0) return false;
435+
if ( cnt == 0 ) return false;
418436

419437
uint16_t rd_ptr = idx2ptr(f->depth, rd_idx);
420438

@@ -431,18 +449,17 @@ static uint16_t _tu_fifo_peek_n(tu_fifo_t* f, void * p_buffer, uint16_t n, uint1
431449
uint16_t cnt = _ff_count(f->depth, wr_idx, rd_idx);
432450

433451
// Check overflow and correct if required
434-
if (cnt > f->depth)
452+
if ( cnt > f->depth )
435453
{
436-
_tu_fifo_correct_read_pointer(f, wr_idx);
437-
rd_idx = f->rd_idx;
454+
rd_idx = _ff_correct_read_index(f, wr_idx);
438455
cnt = f->depth;
439456
}
440457

441458
// Skip beginning of buffer
442-
if (cnt == 0) return 0;
459+
if ( cnt == 0 ) return 0;
443460

444461
// Check if we can read something at and after offset - if too less is available we read what remains
445-
if (cnt < n) n = cnt;
462+
if ( cnt < n ) n = cnt;
446463

447464
uint16_t rd_ptr = idx2ptr(f->depth, rd_idx);
448465

@@ -662,7 +679,7 @@ bool tu_fifo_overflowed(tu_fifo_t* f)
662679
void tu_fifo_correct_read_pointer(tu_fifo_t* f)
663680
{
664681
_ff_lock(f->mutex_rd);
665-
_tu_fifo_correct_read_pointer(f, f->wr_idx);
682+
_ff_correct_read_index(f, f->wr_idx);
666683
_ff_unlock(f->mutex_rd);
667684
}
668685

@@ -963,10 +980,9 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info)
963980
if (cnt > f->depth)
964981
{
965982
_ff_lock(f->mutex_rd);
966-
_tu_fifo_correct_read_pointer(f, wr_idx);
983+
rd_idx = _ff_correct_read_index(f, wr_idx);
967984
_ff_unlock(f->mutex_rd);
968985

969-
rd_idx = f->rd_idx;
970986
cnt = f->depth;
971987
}
972988

@@ -988,7 +1004,8 @@ void tu_fifo_get_read_info(tu_fifo_t *f, tu_fifo_buffer_info_t *info)
9881004
info->ptr_lin = &f->buffer[rd_ptr];
9891005

9901006
// Check if there is a wrap around necessary
991-
if (wr_ptr > rd_ptr) {
1007+
if (wr_ptr > rd_ptr)
1008+
{
9921009
// Non wrapping case
9931010
info->len_lin = cnt;
9941011

0 commit comments

Comments
 (0)