/**
 * \file    drv_crc.c
 * \brief   Hardware CRC operations
 *
 * \par     Copyright (c) 2018 UWE Technologies Corp., Ltd. All Rights Reserved.
 * \author  James
 * \date    2018-10-27
 * \version 
 * 
 * \history 
 *  Date        Note
 *  2018-10-27  Original Creation
 * 
 */

#include "drv_crc.h"
#include "sync.h"
#include "drv_reg_intf.h"
#include "reg_def_chip.h"


typedef enum DRV_CRC_MODE_e
{
    DRV_CRC_MODE_INVALID,
    DRV_CRC_MODE_CRC8,
    DRV_CRC_MODE_CRC16,
    DRV_CRC_MODE_CRC32,
    DRV_CRC_MODE_MAX
} DRV_CRC_MODE_t;

/**
 * Set CRC input data direction
 *
 * \param lsb       0: input data MSB first, 1: input data LSB first
 */
#define drv_crc_bit_order_set(lsb)  DRV_REG_FIELD_SET(CRC_CTRL_REG,CRC_BIT_ORDER,lsb)


/**
 * Set CRC input data direction
 *
 * \param mode      2'b00: Reserved; 
 *                  2'b01: CRC8, x^8 + x^5 + x^4 + x^3 + 1
 *                  2'b10: CRC16, x^16 + x^15 + x^2 + 1
 *                  2'b11: CRC32, x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
 */
#define drv_crc_mode_set(mode)      DRV_REG_FIELD_SET(CRC_CTRL_REG,CRC_CALC_MODE,mode)

/**
 * Set CRC initial value
 *
 * \param value     CRC initial value
 */
#define drv_crc_initial_set(value)  DRV_REG_SET(CRC_INIT_REG,value)


/**
 * Input CRC data
 *
 * \param value     CRC input data
 */
#define drv_crc_input_data(value)   DRV_REG_SET(CRC_DATA_REG,value)

/**
 * Get CRC result
 *
 * \return CRC result
 */
#define drv_crc_result_get()        DRV_REG_GET(CRC_RSLT_REG)


u8_t drv_crc8(const u8_t *buf, int len)
{
    drv_crc_bit_order_set(TRUE);
    drv_crc_mode_set(DRV_CRC_MODE_CRC8);
    drv_crc_initial_set(0);
    while( len-- > 0)
        drv_crc_input_data(*(unsigned char *)buf++);
    return drv_crc_result_get();
}

u8_t drv_crc8_msb(u8_t init, const u8_t *buf, int len)
{
    drv_crc_bit_order_set(FALSE);
    drv_crc_mode_set(DRV_CRC_MODE_CRC8);
    drv_crc_initial_set(init);
    while( len-- > 0)
        drv_crc_input_data(*(unsigned char *)buf++);
    return drv_crc_result_get();
}

u16_t drv_crc16(const u8_t *buf, int len)
{
    drv_crc_bit_order_set(TRUE);
    drv_crc_mode_set(DRV_CRC_MODE_CRC16);
    drv_crc_initial_set(0);
    while( len-- > 0)
        drv_crc_input_data(*(unsigned char *)buf++);
    return drv_crc_result_get();
}
u16_t drv_crc16_8005_add(u32_t crc,const u8_t *buf, int len)
{
    drv_crc_bit_order_set(FALSE);
    drv_crc_mode_set(DRV_CRC_MODE_CRC16);
    drv_crc_initial_set(crc);
    while( len-- > 0)
        drv_crc_input_data(*(unsigned char *)buf++);
    return drv_crc_result_get();
}

u32_t drv_crc32(u32_t crc, const void *buf, int len)
{
    drv_crc_bit_order_set(TRUE);
    drv_crc_mode_set(DRV_CRC_MODE_CRC32);
    drv_crc_initial_set(crc);
    while( len-- > 0)
        drv_crc_input_data(*(unsigned char *)buf++);
    return drv_crc_result_get();
}


