#ifndef __UTIL_H__
#define __UTIL_H__

#define Outp32(addr, data) (*(volatile UINT32 *)(addr) = (data))
#define Outp16(addr, data) (*(volatile UINT16 *)(addr) = (data))
#define Outp8(addr, data)  (*(volatile UINT8 *)(addr) = (data))
#define Inp32(addr, data) (data = (*(volatile UINT32 *)(addr)))
#define Inp16(addr, data) (data = (*(volatile UINT16 *)(addr)))
#define Inp8(addr, data)  (data = (*(volatile UINT8 *)(addr)))

void TurnOnLED(UINT32 uWhichLed); // uWhichLed = 1,2,3,4
void TurnOffLED(UINT32 uWhichLed); // uWhichLed = 1,2,3,4
#ifndef BOOT_CODE
void DispSysInfo(void);
#endif

#ifdef DISP_GPIO_REG
#define gpioOutp32(a, d) {UINT32 a2, d2; a2=a; d2=d; Disp("Outp32(\'h%08x, \'h%08x);\n", a2, d2); Outp32(a2, d2);}
#define gpioInp32(a, d) {UINT32 a2, d2; a2=a; Inp32(a2, d2); d=d2; Disp("Inp32(\'h%08x, d); // d=0x%08x\n", a2, d2);}
#else
#define gpioOutp32 Outp32
#define gpioInp32 Inp32
#endif

#define SetBits(uAddr, uBaseBit, uMaskValue, uSetValue) \
{ \
    volatile UINT32 x; \
    gpioInp32(uAddr, x); \
    x &= ~((unsigned)(uMaskValue)<<(uBaseBit)); \
    x |= ((unsigned)(uSetValue)<<(uBaseBit)); \
    gpioOutp32(uAddr, x); \
}

#define Align(x, alignbyte) \
    (((x)+(alignbyte)-1)/(alignbyte)*(alignbyte))

void TuneDelay(void);
#define Delay(x) Delay100us(x)

bool LoadFile(const char *pFilename, UINT32 uDstAddr);
void LoadFile(const char *pFilename, UINT32 uDstAddr, UINT32 &uFileSize);
#define LoadFromFile LoadFile
void SaveToFile(const char* pFilename, UINT32 uSrcAddr, UINT32 fileSize);

int ConvertStrToNum(char *string);
void ConvertRgbToYCbYCr( UINT32 uHsz, UINT32 uVsz, UINT32 uStAddr, UINT32 uDstAddr );
void ConvertRgbToYCbCr420( UINT32 uHsz, UINT32 uVsz, UINT32 uStAddr, UINT32 uDstAddr );
void ConvertNv12ToYuv420(UINT32 uSrcAddrOfY, UINT32 uSrcAddrOfCbCr, UINT32 uPicHsz, UINT32 uPicVsz, UINT32 uDstAddrOfY);
void ConvertNv16ToCBYCRY(UINT32 uSrcAddrOfY, UINT32 uSrcAddrOfCbCr, UINT32 uPicHsz, UINT32 uPicVsz, UINT32 uDstAddrOfY);
void ConvertYuv420ToNv12(UINT32 uSrcAddrOfY, UINT32 uPicHsz, UINT32 uPicVsz, UINT32 uDstAddrOfY);
bool CompareFrameBuffers(UINT32 a0, UINT32 width, UINT32 height, UINT32 a1, UINT32 dispWidth, UINT32 dispHeight,
    UINT32& uMaxAbsDiff, UINT32& uAvgDiff);
void DispStringArray(char* apString[], UINT32 uNumOfFiles);
void ConvertImgTypeToString(IMG_TYPE eBpp, const char* &pStr);
void ConvertImgSzToNumber(IMG_SIZE eSize, UINT32& uHsz, UINT32& uVsz);
void GetFbSize(IMG_TYPE eImgFmt, UINT32 uImgHsz, UINT32 uImgVsz, UINT32& uFbSize);
void GetFbAddr(IMG_TYPE eImgFmt, UINT32 uImgHsz, UINT32 uImgVsz, UINT32 uFbStAddr, UINT32 uNumOfFrm,
    UINT32 uIdx, UINT32& uFbYAddr, UINT32& uFbCAddr);

extern "C"
{
void Copy1b(UINT32 sa, UINT32 da, UINT32 bytes);
void Copy1w(UINT32 sa, UINT32 da, UINT32 uCntOfWords);
bool Compare1b(UINT32 a1, UINT32 a2, UINT32 bytes);
bool Compare1w(UINT32 a1, UINT32 a2, UINT32 uCntOfWords);
bool Compare4w(UINT32 uSrcAddr, UINT32 DstAddr, UINT32 uCntOfWords);
void Dump1b(UINT32 addr, UINT32 bytes);
void Dump1w(UINT32 addr, UINT32 uCntOfWords);
void Copy8w(UINT32 uSrcAddr, UINT32 uDstAddr, UINT32 uCntOf8Words);
void Read8w(UINT32 uSrcAddr, UINT32 uDstAddr, UINT32 uCntOf8Words);
void Write8w(UINT32 uSrcAddr, UINT32 uDstAddr, UINT32 uCntOf8Words);
}
#define Copy8 Copy1b
#define Copy32 Copy1w
#define Compare8 Compare1b
#define Compare32 Compare1w
#define Dump8 Dump1b
#define Dump32 Dump1w

inline UINT32 Stop(void) { while (1); return 0; }
#ifndef BOOT_CODE
#define Assert(b) (!(b) ? Disp("\n %s(line %d)\n", __FILE__, __LINE__), Stop() : 0)
#else
#define Assert(b) (!(b) ? Stop() : 0)
#endif

#endif // __ETC_H__

