/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2023. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */
/******************************************************************************
 * @version: V1.0.0 demo
 ******************************************************************************/

/*!
* @file crc.c
*
* @brief This file contains the user crc function..
*
*/

/* ===========================================  Includes  =========================================== */
#include "crc.h"
#include "string.h"

/* ============================================  Define  ============================================ */

/* ===========================================  Typedef  ============================================ */

/* ==========================================  Variables  =========================================== */
uint8_t g_dmaFinish = 0;     /* DMA Transfer completed flag */
uint8_t g_halfDmaFinish = 0; /* DMA Half-Transfer completed flag */
uint8_t g_dmaTransError = 0; /* DMA Transfer error flag */

uint32_t tmpResult = 0;
CRC_ProtocolType tmpCRCType = CRC_PROTOCOL_32BIT;

uint32_t CRC_data[CRC_DATA_SIZE] =
{
    0x9421FFE0, 0x7C0802A6, 
};



/* ====================================  Functions declaration  ===================================== */
uint32_t CRC_GetCrcResult(void);
void CRC_SetSeedReg(uint32_t seedValue);

/* ======================================  Functions define  ======================================== */

/**
 * CRC_DMACallback
 *
 * @param[in] void
 * @return void
 *
 * @brief CRC_DMA Callback
 */
void CRC_DMACallback(void *device, uint32_t wpara, uint32_t lpara)
{
    if ((wpara & 0x01) == 0x1) /* DMA Transfer completed */
    {
        g_dmaFinish = 1;
        tmpResult = CRC_GetCrcResult();
        printf("CRC result is: 0x%X\r\n", tmpResult);
    }
    if ((wpara & 0x02) == 0x2) /* DMA Half-Transfer completed */
    {
        g_halfDmaFinish = 1;
    }
    if ((wpara & 0x04) == 0x4) /* DMA Transfer error */
    {
        g_dmaTransError = 1;
        printf("error\r\n");
    }
}

/*!
 * @brief CRC DMAInit
 *
 * @param[in] instance: none
 * @return none
 */
void CRC_DMAInit(void)
{
    DMA_ConfigType dma_Config;

    memset(&dma_Config, 0, sizeof(dma_Config));

    dma_Config.memStartAddr = (uint32_t)&CRC_data[0];                  /* memory start address */
    dma_Config.memEndAddr = (uint32_t)&CRC_data[0] + sizeof(CRC_data); /* memory end address */
    dma_Config.periphStartAddr = (uint32_t)(&(CRC->DATAn.DATA32));     /* peripheral address in memory */
    dma_Config.channelEn = ENABLE;                                     /* DMA channel: 0:disable 1:enable */
    dma_Config.finishInterruptEn = ENABLE;                             /* finish interrupt:  0:disable 1:enable */
    dma_Config.halfFinishInterruptEn = ENABLE;                         /* half finish interrupt:  0:disable 1:enable */
    dma_Config.errorInterruptEn = ENABLE;                              /* error interrupt:  0:disable 1:enable */
    dma_Config.channelPriority = DMA_PRIORITY_VERY_HIGH;               /* 0:low; 1:medium; 2:high; 3: very high */
    dma_Config.circular = DISABLE;                                     /* 0:normal mode 1:enable circular mode */
    dma_Config.direction = DMA_READ_FROM_MEM;                          /* 0: DMA read from peripheral; 1: DMA read from memory */
    dma_Config.MEM2MEM = ENABLE;                                       /* 0:DMA mode between memory and peripheral device; 1: DMA mode between memory and memory */
    dma_Config.memByteMode = DMA_MEM_BYTE_MODE_1TIME;                  /* memory word is divided to transfer in 1/2/4 times */
    dma_Config.memIncrement = ENABLE;                                  /* 0:MEM address is fixed; 1: MEM address increment */
    dma_Config.periphIncrement = DISABLE;                              /* 0:Peripheral address is fixed; 1: Peripheral address increment */
    dma_Config.memSize = DMA_MEM_SIZE_32BIT;                           /* 2:32-bit, right now only support 32-bit */
    dma_Config.periphSize = DMA_PERIPH_SIZE_32BIT;                     /* 0:8-bit; 1:16-bit; 2:32-bit; 3:reserved, if PERIPH_INCREMENT is fixed, it will be 32-bit */
    dma_Config.transferNum = CRC_DATA_SIZE;                            /* transfer total transfer numbers: 0~32767, bit 15 should be 0 */
    dma_Config.callBack = CRC_DMACallback;                             /* Set DMA Callback */

    DMA_Init(DMA0_CHANNEL0, &dma_Config);
}

/*!
 * @brief CRC Init
 *
 * @param[in] instance: none
 * @return none
 */
void CRC_InitTest(void)
{
    CRC_ConfigType CrcConfig;
    memset(&CrcConfig, 0, sizeof(CrcConfig));

    CrcConfig.crcProtocolType = tmpCRCType;

    if (tmpCRCType == CRC_PROTOCOL_32BIT)
    {
        CrcConfig.finalXOR = DISABLE;                            /* Enable/disable result XOR */
        CrcConfig.poly = 0x04C11DB7;                             /* CRC polynomial */
        CrcConfig.readTransposeType = CRC_READ_TRANSPOSE_BITS_BYTES;   /* CRC read out without tranpose */
        CrcConfig.writeBytesNumOnce = CRC_WRITE_4_BYTE_ONCE;     /* CRC write 1 byte once */
        CrcConfig.writeTransposeType = (CRC_WriteTransposeType)(CRC_READ_TRANSPOSE_BITS_BYTES ^ 0x03); /* CRC write in without tranpose */
    }
    else
    {
        CrcConfig.finalXOR = DISABLE;                            /* Enable/disable result XOR */
        CrcConfig.poly = 0x1021;                                 /* CRC polynomial */
        CrcConfig.readTransposeType = CRC_READ_TRANSPOSE_BITS_BYTES;   /* CRC read out without tranpose */
        CrcConfig.writeBytesNumOnce = CRC_WRITE_4_BYTE_ONCE;     /* CRC write 1 byte once */
        CrcConfig.writeTransposeType = (CRC_WriteTransposeType)(CRC_READ_TRANSPOSE_BITS_BYTES ^ 0x03); /* CRC write in without tranpose */
    }

    CRC_Init(&CrcConfig);    /* Initialize CRC module */
    CRC_SetSeedReg(CRC32_SEED);  /* Set seed value */
    CRC_DMAInit();
}

/*!
 * @brief CRC_GetCrcResult
 *
 * @param[in] instance: none
 * @return data value
 */
uint32_t CRC_GetCrcResult(void)
{
    uint32_t result = 0;

    /* Get result of CRC calculation */
    result = CRC_GetDataReg();
    result = (CRC_PROTOCOL_32BIT == CRC_GetProtocolType()) ? result : ((uint16_t)result);

    return result;
}

/*!
 * @brief CRC_SetSeedReg
 *
 * @param[in] instance: seed value
 * @return none
 */
void CRC_SetSeedReg(uint32_t seedValue)
{
    CRC_SetSeedOrDataMode(CRC_DATA_IS_SEED);
    /* Set seed value */
    CRC_SetDataReg(seedValue);
    CRC_SetSeedOrDataMode(CRC_DATA_IS_DATA);
}

/* =============================================  EOF  ============================================== */
