#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;
}