#include "UartProtocol.h"
#include "PicBin.h"
#include <stdint.h>
#define NULL 0
extern uint8_t UartRevBuff[0x1000];
extern uint32_t UartRevCnts;
uint8_t *GetUartRecvData(uint32_t *UartRecvBufLen, uint32_t *UartRecvPos)
{
    *UartRecvBufLen = 0x1000;
    *UartRecvPos = UartRevCnts;
    return UartRevBuff;
}

void UartSendData(uint8_t *data, uint32_t len)
{
    UART_Ch2_Send_Multiple_Byte(data, len);
}

void DisplayNum(uint8_t page, DISPLAY_NUM_ST *pNumData, int32_t NumVal)
{
    uint8_t j = 0;
    uint8_t i = 0;
    int32_t TmpNum;
    uint16_t tmpIndex = 0;
    uint8_t PointFrontRearBlank = 2;
    uint16_t DotPosition = 0;
    uint8_t DotInterval = 0;
	uint16_t NumberList[20];
    DotInterval = 3;
    DotPosition = pNumData->DecimalNum;
    DotPosition <<= 8;
    TmpNum = NumVal;
    if (TmpNum < 0) {        
        TmpNum = -TmpNum;
    }
    do {
        NumberList[tmpIndex ++] = pNumData->NumList[(TmpNum % 10)];
        i++;
        TmpNum /= 10;
        if (i == pNumData->DecimalNum) {
            if (pNumData->NumList[NUM_POINT] != NULL) {
		        NumberList[tmpIndex ++] = pNumData->NumList[NUM_POINT];
            }
        }
    } while (TmpNum != 0u);
    if (pNumData->DecimalNum != 0u) {
        while ((i - 1u) < pNumData->DecimalNum) {
            NumberList[tmpIndex ++] = pNumData->NumList[0];
            i++;
            if (i == pNumData->DecimalNum) {
                if (pNumData->NumList[NUM_POINT] != NULL) {
		            NumberList[tmpIndex ++] = pNumData->NumList[NUM_POINT];
                }
            }
        }
    }
    if (pNumData->MinDigits != 0u) {
        if ((i - 1) < pNumData->MinDigits) {
            for (j = i; j < pNumData->MinDigits; j++) {
                NumberList[tmpIndex ++] = pNumData->NumList[0];
                i++;
            }
        }
    }
    if (NumVal < 0) {
        if (pNumData->NumList[NUM_LINE] != NULL) {
            NumberList[tmpIndex ++] = pNumData->NumList[NUM_LINE];
        }
    }
    
    SetPagePicGroup(page, pNumData->NumInterval, pNumData->x, pNumData->y, NumberList, GROUP_ALIGN_CENTER | (tmpIndex & 0x3f), DotPosition | DotInterval, TFT_ROT_0);
}

/***************** Read 630 ************************/
#define READ_MCU_DATA_MAX 0x800
enum {
    READ630_IDLE,
    READ630_WAITING_RESP,
    READ630_RECV_RESP_DATA,
    READ630_RECV_OFFSET_LEN,
    READ630_RECV_BACKUP_DATA_RESP,
    READ630_RECV_BACKUP_DATA_CRC,
};

static uint8_t Read630State = READ630_IDLE;
static uint32_t ReqDataBufAddr = 0;
static uint32_t ReqDataLen = 0;
static uint32_t RespDataOffset = 0;
static uint32_t RespDataLen = 0;
static uint32_t RespDataCrc = 0;
static uint32_t WriteBackupDataCrc = 0;
uint32_t ProcMcuOrBackupData(READ_ARK630_CMD type, uint32_t offset, uint32_t len, uint8_t uotbuffer[])
{
    uint32_t ret32 = 0;

    if (type == REQ_DATA) {
        if (len <= READ_MCU_DATA_MAX) {
            ReqDataBufAddr = (uint32_t)uotbuffer;
            ReqDataLen = len;
            memset((uint8_t *)ReqDataBufAddr, 0, ReqDataLen);
            PackedTransfer_GetMcuData(offset, (uint16_t)len);
            Read630State = READ630_WAITING_RESP;
            RespDataOffset = 0;
            RespDataLen = 0;
        } else {
            ret32 = 1;
        }
    } else if (type == WRITE_BACKUP_DATA) {
        if (len <= READ_MCU_DATA_MAX) {
            PackedTransfer_WriteBackupData(offset, uotbuffer, (uint16_t)len);
            Read630State = READ630_WAITING_RESP;
            RespDataOffset = 0;
            RespDataLen = 0;
        } else {
            ret32 = 1;
        }
    } else if (type == GET_BACKUP_DATA_CRC) {
        PackedTransfer_GetBackupDataCrc(offset, len);
        Read630State = READ630_WAITING_RESP;
        RespDataOffset = 0;
        RespDataLen = 0;
    } else if (type == GET_STATUS) {
        if (Read630State == READ630_WAITING_RESP) {
            ret32 = 2;
        } else if (Read630State == READ630_RECV_RESP_DATA) {
            ret32 = RespDataOffset + RespDataLen;
        } else if (Read630State == READ630_RECV_OFFSET_LEN) {
            ret32 = RespDataOffset;
        } else if (Read630State == READ630_RECV_BACKUP_DATA_CRC) {
            ret32 = RespDataCrc;
        } else if (Read630State == READ630_RECV_BACKUP_DATA_RESP) {
            ret32 = RespDataOffset + RespDataLen;
        } else {
            Read630State = READ630_IDLE;
        }
    } else if ((type == GET_APP_DATA_OFFSET) || (type == GET_BACKUP_DATA_OFFSET)) {
        PackedTransfer_GetDataOffsetLen(type);
        Read630State = READ630_WAITING_RESP;
        RespDataOffset = 0;
        RespDataLen = 0;
    } else {
        ;
    }

    return ret32;
}

void GetDataBuf(uint32_t *pAddr, uint32_t *pLen)
{
    *pAddr = ReqDataBufAddr;
    *pLen = ReqDataLen;
}

void SetRecvDataSt(RECV_MCU_DATA_TYPE type, uint32_t addr, uint32_t len, uint32_t crc)
{
    RespDataOffset = addr;
    RespDataLen = len;
    RespDataCrc = crc;
    if (type == RECV_TYPE_DATA) {
        Read630State = READ630_RECV_RESP_DATA;
    } else if (type == RECV_TYPE_OFFSET_LEN) {
        Read630State = READ630_RECV_OFFSET_LEN;
    } else if (type == RECV_TYPE_WRITE_BACKUP_RESP) {
        Read630State = READ630_RECV_BACKUP_DATA_RESP;
        WriteBackupDataCrc = crc;
    } else if (type == RECV_TYPE_BACKUP_CRC) {
        Read630State = READ630_RECV_BACKUP_DATA_CRC;
    } else {
        ;
    }
}
/***************** Read 630 end ************************/

/* Test */
static uint8_t TestReadBuf[READ_MCU_DATA_MAX];
static uint32_t TestDataLen = 0;
static uint32_t TestDataCrC = 0;
static uint32_t ReadOffset = 0;
static uint32_t CalcCrcVal = 0xffffffff;
static uint32_t TestCycleNum = 0;

static uint32_t CalcCrc32(uint8_t *buf, int Len, uint32_t InitVal)
{
    int i;
    int n = 0;
    uint32_t crc = InitVal; // Initial value
    for (n = 0; n < Len; n++) {
        crc ^= (uint32_t)buf[n] << 24; // crc ^= *data; data++;
        for (i = 0; i < 8; ++i) {
            if (crc & 0x80000000) {
                crc = (crc << 1) ^ 0x04C11DB7; // 0xEDB88320= reverse 0x04C11DB7
            } else {
                crc = (crc << 1);
            }
        }
    }
    return crc;
}

void TestRead630Update(void)
{
    uint32_t tmpLen;
    static uint8_t readSt = 0;
    static uint16_t getStRetryCnts = 0;
    if (TestDataLen == 0) {
        if (readSt == 0) {
            readSt = 1;
            ProcMcuOrBackupData(GET_APP_DATA_OFFSET, 0, 0, 0);
            getStRetryCnts = 500;
        } else {
            TestDataLen = ProcMcuOrBackupData(GET_STATUS, 0, 0, 0);
            if ((TestDataLen != 0) || (--getStRetryCnts == 0)) {
                if (TestDataLen != 0) {
                    TestDataLen = RespDataLen;
                    TestDataCrC = RespDataCrc;
                    ReadOffset = 0;
                    CalcCrcVal = 0xffffffff;
                }
                readSt = 0;
            }
        }
    } else {
        if (readSt == 0) {
            readSt = 1;
            ProcMcuOrBackupData(REQ_DATA, ReadOffset, READ_MCU_DATA_MAX, TestReadBuf);
            getStRetryCnts = 500;
            ReadOffset += READ_MCU_DATA_MAX;
        } else {
            tmpLen = ProcMcuOrBackupData(GET_STATUS, 0, 0, 0);
            if (ReadOffset == tmpLen) {
                if (ReadOffset < TestDataLen) {
                    CalcCrcVal = CalcCrc32(TestReadBuf, READ_MCU_DATA_MAX, CalcCrcVal);
                    readSt = 0;
                } else {
                    CalcCrcVal = CalcCrc32(TestReadBuf, TestDataLen - (ReadOffset - READ_MCU_DATA_MAX), CalcCrcVal);
                    if (CalcCrcVal != TestDataCrC) {
                        while (1) {
                            RTE_WDT_Clear();
                        }
                    } else {
                        TestCycleNum++;
                    }
                    getStRetryCnts = 500;
                    TestDataLen = 0;
                    TestDataCrC = 0;
                    readSt = 0;
                }
            }
            if (--getStRetryCnts == 0) {
                ReadOffset -= READ_MCU_DATA_MAX;
                readSt = 0;
            }
        }
    }
}
/* Test end */

/* Test */
static uint32_t TestBackupDataLen = 0;
static uint32_t TestBackupDataOffset = 0;
static uint32_t TestBackupDataOffsetEnd = 0;
static uint32_t TestBackupDataCrc = 0;
static uint8_t *pData = (uint8_t*)0x40400;
void TestWrite630Backup(void)
{
    static  int readstep = 0;
    uint32_t tmpRet;
    static uint8_t readSt = 0;
    static uint16_t getStRetryCnts = 0;

    TestBackupDataLen = 0x100000;
    if (TestBackupDataOffset == 0) {
        if (readSt == 0) {
            readSt = 1;
            ProcMcuOrBackupData(GET_BACKUP_DATA_OFFSET, 0, 0, NULL);
            getStRetryCnts = 500;
        } else {
            tmpRet = ProcMcuOrBackupData(GET_STATUS, 0, 0, NULL);
            if ((tmpRet != 2) || (--getStRetryCnts == 0)) {
                if (tmpRet != 2) {
                    TestBackupDataOffset = tmpRet;
                    TestBackupDataOffsetEnd = TestBackupDataOffset + TestBackupDataLen;
                }
                readSt = 0;
            }
        }
    } else if (TestBackupDataCrc == 0) {
        if (readSt == 0) {
            readSt = 1;
            ProcMcuOrBackupData(GET_BACKUP_DATA_CRC, TestBackupDataOffset, TestBackupDataLen, NULL);
            getStRetryCnts = 500;
        } else {
            tmpRet = ProcMcuOrBackupData(GET_STATUS, 0, 0, NULL);
            if ((tmpRet != 2) || (--getStRetryCnts == 0)) {
                if (tmpRet != 2) {
                    TestBackupDataCrc = tmpRet;
                }
                readSt = 0;
            }
        }
    } else {
#if 1
        if (readSt == 0) {
            readSt = 1;
            ProcMcuOrBackupData(REQ_DATA, TestBackupDataOffset, READ_MCU_DATA_MAX, TestReadBuf);
            getStRetryCnts = 500;
            TestBackupDataOffset += READ_MCU_DATA_MAX;
        } else {
            tmpRet = ProcMcuOrBackupData(GET_STATUS, 0, 0, 0);
            if (TestBackupDataOffset == tmpRet) {
                if (TestBackupDataOffset < TestBackupDataOffsetEnd) {
                    readSt = 0;
                } else {
                    readSt = 0;
                }
            }
            if (--getStRetryCnts == 0) {
                TestBackupDataOffset -= READ_MCU_DATA_MAX;
                readSt = 0;
            }
        }
#else
        if (readSt == 0) {
            readSt = 1;
            ProcMcuOrBackupData(WRITE_BACKUP_DATA, TestBackupDataOffset, READ_MCU_DATA_MAX, pData);
            getStRetryCnts = 1500;
            TestBackupDataOffset += READ_MCU_DATA_MAX;
            pData += READ_MCU_DATA_MAX;
        } else {
            tmpRet = ProcMcuOrBackupData(GET_STATUS, 0, 0, 0);
            if (TestBackupDataOffset == tmpRet) {
                if (TestBackupDataOffset < TestBackupDataOffsetEnd) {
                    readSt = 0;
                } else {
                    readSt = 0;
                }
            }
            if (--getStRetryCnts == 0) {
                TestBackupDataOffset -= READ_MCU_DATA_MAX;
                pData -= READ_MCU_DATA_MAX;
                readSt = 0;
            }
        }
#endif
    }
}
/* Test end */
