#include "FlashCheckSum.h"
#include "dr7f701441.dvf.h"
#include "Watchdog.h"

static unsigned int SwapData_32(unsigned int Data)
{
	unsigned int RetVal = Data;
	RetVal = ((RetVal >> 1) & 0x55555555) | ((RetVal << 1) & 0xaaaaaaaa);
	RetVal = ((RetVal >> 2) & 0x33333333) | ((RetVal << 2) & 0xcccccccc);
	RetVal = ((RetVal >> 4) & 0x0f0f0f0f) | ((RetVal << 4) & 0xf0f0f0f0);
	RetVal = ((RetVal >> 8) & 0x00ff00ff) | ((RetVal << 8) & 0xff00ff00);
	RetVal = ((RetVal >> 16) & 0x0000ffff) | ((RetVal << 16) & 0xffff0000);

	return RetVal;
}

unsigned int CRC32_VAL;
static void CheckCrc32(unsigned char *buf, int len)
{
	int   i;
	int n = 0;
	unsigned char tmp = 0;
	unsigned int crc = CRC32_VAL;  // Initial value
	for (n = 0; n < len; n++) {
		tmp = buf[n];
		tmp = (tmp >> 4) | (tmp << 4);
		tmp = (((tmp & 0xcc) >> 2) | ((tmp & 0x33) << 2));
		tmp = (((tmp & 0xaa) >> 1) | ((tmp & 0x55) << 1));
		crc ^= (unsigned int)(tmp) << 24;
		for (i = 0; i < 8; ++i) {
			if (crc & 0x80000000L) {
				crc = (crc << 1) ^ 0x04C11DB7;
			} else {
				crc <<= 1;
			}
		}
	}
    CRC32_VAL = crc;
	return;
}


unsigned char CheckSpiFlashCRC(void)
{
    unsigned char TmpRet = 0;
    unsigned int BinCrc = REAL_FLASHCHECKSUM;   //*((unsigned int *)(SPI_START_ADDR + 0x8u));
    unsigned int BinCrcLen = SPI_ADDR_RANGE;  //*((unsigned int *)(SPI_START_ADDR));
    unsigned int CheckCrcAddr = SPI_START_ADDR; //SPI_START_ADDR + 0x20u;
    unsigned int tmp;
    unsigned int CheckCrc = 0;
    unsigned int i;
    unsigned int EndData = 0;
    DCRA0ISZ = 0;
    DCRA0POL = 0;
    DCRA0COUT = 0xffffffff;
    if (/*(BinCrcLen > 0x00000020) && */(BinCrcLen < 0x08000000))
    {
        for (i = 0; i < (BinCrcLen / 4); i++)
        {
            WDT_Clear();
            tmp = *((unsigned int *)(CheckCrcAddr + (i * 4)));
            DCRA0CIN = tmp;
            CheckCrc = DCRA0COUT;
        }
        tmp = *((unsigned int *)(CheckCrcAddr + (i * 4)));
        if (BinCrcLen % 4 != 0u) {
            CheckCrc = CheckCrc ^ 0xffffffff;
            CheckCrc = SwapData_32(CheckCrc);
            CRC32_VAL = CheckCrc;
            CheckCrc32(&tmp, BinCrcLen % 4);
			CheckCrc = SwapData_32(CRC32_VAL);
        	CheckCrc = CheckCrc ^ 0xffffffff;
        }
        
        if (CheckCrc == BinCrc)
        {
            TmpRet = 1;
        }
    }
    return TmpRet;
}