#ifndef _apl_types_endianapi_h_
#define _apl_types_endianapi_h_
/*----------------------------------------------------------------------------
** SUMMARY: Endian Access Interface (EAI)
**
** DESCRIPTION:
**  This file provides a series of macros that can be used to safely 
**  access data when the endianess of the platform must be account for.
**
** CONFIGURATION 
** -------------
**  COMPILE:        USE_APL_LITTLE_ENDIAN
**                  USE_APL_BIG_ENDIAN                     
**                                            
**  APPLICATION:    none.
**
**  PLATFORM:       none.
**
----------------------------------------------------------------------------*/

#include "aplcfg.h"             /* For: Endian configuraiton */
#include "apl/types/types.h"    /* For: basic types */


#ifdef __cplusplus
extern "C" {
#endif


/* There is NO DEFAULT for endian selection.  If the application uses this
   interface, it must explicity define the target endian type.
*/
#if !defined(USE_APL_BIG_ENDIAN) && !defined(USE_APL_LITTLE_ENDIAN)
#error The application MUST define the endianess of the target!
#endif



/*
** LITTLE ENDIAN MACROS
** These macros safely read-from odd addresses. 
*/
#ifdef USE_APL_LITTLE_ENDIAN

/** Read/Write the LSB of the 2byte word */
#define APL_LOBYTE_WORD(w)                              (*((AplByte*)(&(w))))

/** Read/Write the MSB of the 2byte word */
#define APL_HIBYTE_WORD(w)                              (*(((AplByte*)(&(w)))+1))


/** Read/Write the LSB of the 4byte double word */
#define APL_BYTE0_DWORD(w)                              APL_LOBYTE_WORD(w)

/** Read/Write the LSB+1 of the 4byte double word */
#define APL_BYTE1_DWORD(w)                              APL_HIBYTE_WORD(w)

/** Read/Write the LSB+2 of the 4byte double word */
#define APL_BYTE2_DWORD(w)                              (*(((AplByte*)(&(w)))+2))

/** Read/Write the MSB of the 4byte double word */
#define APL_BYTE3_DWORD(w)                              (*(((AplByte*)(&(w)))+3))


/** Read/Write the LSW of the 4byte double word */
#define APL_LOWORD_DWORD(dw)                            (*((Apl16u*)(&(dw))))

/** Read the 'middle word' of the 4byte double word */
#define APL_MIDWORD_DWORD(dw)                           ((Apl16u)(((Apl16u)AplByte2_DWORD(dw))<<8)|((Apl16u)AplByte1_DWORD(dw)))

/** Read/Write the MSW of the 4byte double word */
#define APL_HIWORD_DWORD(dw)                            (*(((Apl16u*)(&(dw)))+1))




/*
** BIG ENDIAN MACROS
** These macros safely read-from odd addresses. 
*/
#else   

/** Read/Write the MSB of the 2byte word */
#define APL_HIBYTE_WORD(w)                              (*((AplByte*)(&(w))))

/** Read/Write the LSB of the 2byte word */
#define APL_LOBYTE_WORD(w)                              (*(((AplByte*)(&(w)))+1))


/** Read/Write the MSB of the 4byte double word */
#define APL_BYTE3_DWORD(w)                              APL_HIBYTE_WORD(w)

/** Read/Write the LSB+2 of the 4byte double word */
#define APL_BYTE2_DWORD(w)                              APL_LOBYTE_WORD(w)

/** Read/Write the LSB+1 of the 4byte double word */
#define APL_BYTE1_DWORD(w)                              (*(((AplByte*)(&(w)))+2))

/** Read/Write the LSB of the 4byte double word */
#define APL_BYTE0_DWORD(w)                              (*(((AplByte*)(&(w)))+3))


/** Read/Write the MSW of the 4byte double word */
#define APL_HIWORD_DWORD(dw)                            (*((Apl16u*)(&(dw))))

/** Read the 'middle word' of the 4byte double word */
#define APL_MIDWORD_DWORD(dw)                           ((Apl16u)(((Apl16u)AplByte2_DWORD(dw))<<8)|((Apl16u)AplByte1_DWORD(dw)))

/** Read/Write the LSW of the 4byte double word */
#define APL_LOWORD_DWORD(dw)                            (*(((Apl16u*)(&(dw)))+1))


#endif  /* end USE_APL_LITTLE_ENDIAN */


#ifdef __cplusplus
}
#endif

/*--------------------------------------------------------------------------*/
#endif  /* end _apl_types_endianapi_h_ */
