openmv/drivers/dave2d/include/dave_dlist.h
iabdalkader daf2bb30da misc: Restructure repo.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
2025-04-13 08:28:34 +02:00

259 lines
9.5 KiB
C

/*--------------------------------------------------------------------------
* Project: D/AVE
* File: dave_dlist.h (%version: 20 %)
* created Thu Feb 17 21:44:45 2005 by hh04027
*
* Description:
* %date_modified: Thu Jan 25 17:39:49 2007 % (%derived_by: hh74026 %)
*
* Changes:
* 2005-12-22 CSe - added d2_copydlist_vidmem_intern()
* - renamed block->vram to block->vidmem for consistency
* - big endian change + define for BIG_ENDIAN
* 2005-02-28 CSe - added d2_cacheflushdlist_intern()
* 2006-05-10 CSe - added d2_mapdlist_vidmem_intern()
* 2006-10-30 CSe - removed counting of dlist used slots
* 2006-11-07 CSe - changes for new 'd2_df_low_localmem' mode
* 2006-11-30 CSe - fixed insertion of dlist special commands
* 2007-01-26 CSe - made 'low localmem' mode configurable
* 2007-03-08 CSe - optimized dlist copying and flushing
* 2008-01-14 ASc - changed comments from C++ to C, removed tabs
* 2012-08-23 MRe - extended dlist structure for dlist lists
* 2012-09-25 BSp - MISRA cleanup
* 2017-07-27 HFu - clearly commented and renamed d2_insertwait...dlist_intern functions
*-------------------------------------------------------------------------- */
#ifndef __1_dave_dlist_h_H
#define __1_dave_dlist_h_H
/*--------------------------------------------------------------------------- */
#define D2_DLISTWRITES(x, y) d2_add2dlist_intern( handle, x, y ) /* PRQA S 3453 */ /* $Misra: #MACRO_FXN_FORWARD $*/
#define D2_DLISTWRITEU(x, y) d2_add2dlist_intern( handle, x, (d2_s32) (y) ) /* PRQA S 3453 */ /* $Misra: #MACRO_FXN_FORWARD $*/
/*-------------------------------------------------------------------------- */
#define D2_DLISTBLOCKSIZE 204 /* blocksize: initial number and number of entrys to grow when dlist is full (5*4*204 = approx. 4kBytes) */
#define D2_DLISTSCRATCH 64 /* number of scratch buffer entries */
#define D2_DLISTSHRINKDELAY 60 /* number of frames, the amount of display list blocks needs to be too large, before it is reduced */
/*--------------------------------------------------------------------------- */
typedef struct _d2_dlist_vidmem_blocks
{
void ** blocks; /* array of dlist blocks in vidmem */
d2_u32 num_blocks; /* number of entries in above array */
d2_u32 block_size; /* size of blocks in vidmem */
void ** currentblock; /* pointer into above array of vidmem blocks */
d2_s8 * currentaddress; /* pointer into vidmem inside current block (multiple local blocks are copied into one vidmem block) */
d2_u32 num_slices; /* one vidmem blocks consists of multiple slices (see above) */
d2_u32 slicesleft; /* number of slices left */
d2_u32 blocksleft; /* number of vidmem blocks left */
} d2_dlist_vidmem_blocks;
typedef struct _d2_dlist_entry
{
union d2_addresstag /* register tag field (4 reg indices) */
{
d2_u32 mask;
d2_u8 array[4];
} address;
d2_s32 value[4]; /* register value field */
} d2_dlist_entry;
typedef struct _d2_dlist_block
{
struct _d2_dlist_block *next;
d2_dlist_entry * block; /* display list memory */
d2_u32 quantity; /* number of dlist_entries */
d2_s32 * jump; /* pointer to addressentry of next display list or null */
void * vidmem; /* address of memoryblock in videoram or null */
} d2_dlist_block ;
typedef struct _d2_dlist
{
d2_device *device;
d2_dlist_block *firstblock;
d2_dlist_block *currentblock;
d2_dlist_block *resumeblock;
d2_dlist_entry *position;
d2_dlist_vidmem_blocks *vidmem_blocks; /* used in low local memory mode only */
d2_u32 tagindex;
d2_u32 blocksize;
d2_u32 stepsize;
d2_s32 busy;
d2_u32 shrinkcount;
d2_u32 count;
void * dlist_addresses; /* list of dlist start addresses accessible by Dave */
d2_s16 dlist_addresses_max; /* max number of dlist start addresses in dlist_addresses */
d2_s16 dlist_addresses_cur; /* current number of dlist start addresses in dlist_addresses */
} d2_dlist;
typedef struct _d2_dlist_scratch_entry
{
d2_u32 reg;
d2_s32 value;
} d2_dlist_scratch_entry;
typedef struct _d2_lowlocalmem_mode
{
d2_dlist_block *dlist_buffer; /* two dlist blocks linked as ring */
d2_u32 vidmemblocksizefactor; /* factor for size of blocks in vidmem relative to local size */
d2_u32 vidmemblocks; /* maximum number of dlist blocks in vidmem */
} d2_lowlocalmem_mode;
/*--------------------------------------------------------------------------- */
D2_EXTERN void d2_paddlist_intern( d2_dlist *dlist );
D2_EXTERN void d2_growdlist_intern( d2_dlist *dlist );
D2_EXTERN d2_dlist_block * d2_alloc_dlistblock_intern( const d2_device *handle, d2_u32 size );
D2_EXTERN void d2_free_dlistblock_intern( const d2_device *handle, d2_dlist_block *data );
D2_EXTERN d2_s32 d2_initdlist_intern( d2_device *handle, d2_dlist *dlist, d2_u32 initialsize );
D2_EXTERN void d2_deinitdlist_intern(const d2_dlist *dlist);
D2_EXTERN void *d2_preparedlist_read_intern( const d2_device *handle, d2_dlist *dlist, d2_s32 reset );
D2_EXTERN void d2_nextdlistblock_intern( d2_dlist *dlist );
D2_EXTERN d2_u32 d2_executedlist_intern( const d2_device *handle, d2_dlist_entry *block );
D2_EXTERN void d2_copydlist_vidmem_intern( const d2_dlist *dlist );
D2_EXTERN void d2_mapdlist_vidmem_intern( const d2_dlist *dlist );
D2_EXTERN void d2_cacheflushdlist_intern( const d2_dlist *dlist );
D2_EXTERN d2_s32 d2_insertwaitpipedlist_intern( d2_device *handle );
D2_EXTERN d2_s32 d2_insertwaitfulldlist_intern( d2_device *handle );
D2_EXTERN void d2_resetdlist_intern( d2_dlist *dlist );
D2_EXTERN void d2_scratch2dlist_intern( d2_device *handle );
D2_EXTERN void d2_clear_dlistlist_intern( const d2_device *handle, d2_dlist *dlist );
D2_EXTERN d2_s32* d2_add_dlistlist_intern( const d2_device *handle, d2_dlist *dlist, const void *dlistaddress );
/*--------------------------------------------------------------------------- */
/* call only when usedslots>0
* assumes full dlist_entries. padded entries supported at end of list only */
static D2_INLINE d2_dlist_entry* d2_getdlist_intern( d2_dlist *dlist ) /* PRQA S 1527 */ /* $Misra: #PERF_INLINE_FUNC $*/ /* PRQA S 3219, 3450, 3480 */ /* $Misra: #UTIL_INLINE_FUNC $*/
{
d2_dlist_entry *current;
current = dlist->position;
dlist->position++;
dlist->blocksize--;
if (dlist->blocksize < 1)
{
/* this block ran empty, setup for next read */
d2_dlist_block *n = dlist->currentblock->next;
if(NULL != n)
{
/* switch to next block */
dlist->position = n->block;
dlist->blocksize = n->quantity;
dlist->currentblock = n;
}
}
return current;
}
/* insert a jump into the dlist to target, return patch address */
static D2_INLINE d2_s32* d2_insertdlistjump_intern( d2_dlist *dlist, const void *target ) /* PRQA S 1527 */ /* $Misra: #PERF_INLINE_FUNC $*/ /* PRQA S 3219, 3450, 3480 */ /* $Misra: #UTIL_INLINE_FUNC $*/
{
d2_s32 *patch;
/* this block ran empty. insert dlist-jump and mark end */
dlist->position->address.mask = D2_DLISTSTART | 0x80808000u;
dlist->position->value[0] = (d2_s32)target;
/* remember value offset for later patching */
patch = & dlist->position->value[0];
dlist->currentblock->jump = patch;
/* skip jump */
dlist->position = (d2_dlist_entry*) (((d2_s32 *)dlist->position) + 2);
dlist->tagindex = 0;
return patch;
}
/* store a end of dlist special word at current position */
static D2_INLINE void d2_insertdlistspecial_intern( d2_dlist *dlist, d2_u32 argument ) /* PRQA S 1527 */ /* $Misra: #PERF_INLINE_FUNC $*/ /* PRQA S 3219, 3450, 3480 */ /* $Misra: #UTIL_INLINE_FUNC $*/
{
d2_u32 tagIndex = dlist->tagindex;
d2_dlist_entry *pos = dlist->position;
switch(tagIndex)
{
case 0:
/* list already closed -> the address word is not needed */
pos->address.mask = 0xffu | (argument << 8);
dlist->position = (d2_dlist_entry *) ((d2_s32*)pos + 1);
break;
case 1:
/* already one entry in list */
pos->address.mask &= 0x000000ffu;
pos->address.mask |= 0x80808000u;
pos->value[tagIndex] = (d2_s32) (0xffu | (argument << 8));
dlist->position = (d2_dlist_entry *) ((d2_s32*)pos + 3);
break;
case 2:
/* already two entries in list */
pos->address.mask &= 0x0000ffffu;
pos->address.mask |= 0x80800000u;
pos->value[tagIndex] = (d2_s32) (0xffu | (argument << 8));
dlist->position = (d2_dlist_entry *) ((d2_s32*)pos + 4);
break;
case 3:
/* already three entries in list */
pos->address.mask &= 0x00ffffffu;
pos->address.mask |= 0x80000000u;
pos->value[tagIndex] = (d2_s32) (0xffu | (argument << 8));
dlist->position++;
break;
default:
break;
}
/* fix tag */
dlist->tagindex = 0;
dlist->blocksize--;
/* make sure not to go beyond end of block in case the list is not finished!! */
if(0 == (argument & 1))
{
if(dlist->blocksize <= 1)
{
d2_nextdlistblock_intern(dlist);
}
}
}
/*--------------------------------------------------------------------------- */
#endif