#ifndef __CRC_H
#define __CRC_H

/******************************************************************************
 *
 *                  CRC PERIPHERAL LIBRARY HEADER FILE
 *
 ******************************************************************************
 * FileName:        crc.h
 * Dependencies:    See include below
 * Processor:       PIC24
 * Compiler:        MPLAB C30
 * Company:         Microchip Technology, Inc.
 *
 * Software License Agreement
 * The software supplied herewith by Microchip Technology Incorporated
 * (the “Company”) for its PICmicro® Microcontroller is intended and
 * supplied to you, the Company’s customer, for use solely and
 * exclusively on Microchip PICmicro Microcontroller products. The
 * software is owned by the Company and/or its supplier, and is
 * protected under applicable copyright laws. All rights are reserved.
 * Any use in violation of the foregoing restrictions may subject the
 * user to criminal sanctions under applicable laws, as well as to
 * civil liability for the breach of the terms and conditions of this
 * license.
 *
 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 *
 *****************************************************************************/

#include "Generic.h"
#include "PIC24F_periph_features.h"

/* List of SFRs for CRC */
/* This list contains the SFRs with default (POR) values to be used for configuring CRC */
/* The user can modify this based on the requirement */


/*****************************************************************************
 * Following Macros can be used as an input to Module Configuration Functions
 * Ex : CRC_Config_INTR(CRC_INTR_SETUP_VAL)
*****************************************************************************/

/* defines for Timer Interrupts */
#define CRC_INT_PRIOR_7         0x0007      /* 111 = Interrupt is priority 7 */
#define CRC_INT_PRIOR_6         0x0006      /* 110 = Interrupt is priority 6 */
#define CRC_INT_PRIOR_5         0x0005      /* 101 = Interrupt is priority 5 */
#define CRC_INT_PRIOR_4         0x0004      /* 100 = Interrupt is priority 4 */
#define CRC_INT_PRIOR_3         0x0003      /* 011 = Interrupt is priority 3 */
#define CRC_INT_PRIOR_2         0x0002      /* 010 = Interrupt is priority 2 */
#define CRC_INT_PRIOR_1         0x0001      /* 001 = Interrupt is priority 1 */
#define CRC_INT_PRIOR_0         0x0000      /* 000 = Interrupt is priority 0 */

#define CRC_INT_ENABLE          0x0008      /* Interrupt Enable */
#define CRC_INT_DISABLE         0x0000      /* Interrupt Disable */

/*****************************************************************************/
/* Configuration Registers Defaults */
/*****************************************************************************/
#define CRCXOR_VAL              0x0000       /* Polynomial Value */
#define CRCCON_VAL              0x0000

/* CRCCON Register Configuration Bit Definitions */
#define CRC_IDLE_STOP    0x2000 /*stop CRC module in Idle mode */
#define CRC_IDLE_CON     0x0000 /*continue CRC module in Idle mode */
#define CRC_IDLE_MASK    (~CRC_IDLE_CON)

#define CRC_POLYNOMIAL_LEN1     0x0000
#define CRC_POLYNOMIAL_LEN2     0x0001 
#define CRC_POLYNOMIAL_LEN3     0x0002 
#define CRC_POLYNOMIAL_LEN4     0x0003 
#define CRC_POLYNOMIAL_LEN5     0x0004 
#define CRC_POLYNOMIAL_LEN6     0x0005 
#define CRC_POLYNOMIAL_LEN7     0x0006 
#define CRC_POLYNOMIAL_LEN8     0x0007 
#define CRC_POLYNOMIAL_LEN9     0x0008 
#define CRC_POLYNOMIAL_LEN10    0x0009 
#define CRC_POLYNOMIAL_LEN11    0x000A
#define CRC_POLYNOMIAL_LEN12    0x000B
#define CRC_POLYNOMIAL_LEN13    0x000C
#define CRC_POLYNOMIAL_LEN14    0x000D
#define CRC_POLYNOMIAL_LEN15    0x000E
#define CRC_POLYNOMIAL_LEN16    0x000F
#define CRC_POLYNOMIAL_MASK     (~CRC_POLYNOMIAL_LEN16)

#define CRC_START_SERIAL_SHIFT  0x0010   /* Start CRC serial shifter */
#define CRC_SERIAL_SHIFT_OFF    0x0000   /* CRC serial shifter turned off */
#define CRC_SERIAL_SHIFT_MASK   (~CRC_START_SERIAL_SHIFT)


#ifdef _CRC_PROG_V1

/*****************************************************************************
 * After the CRC module has been properly configured, you may wish to use the
 * macros below to modify the Configuration bits during runtime.
*****************************************************************************/

/* Macros to  Enable/Disable interrupts and set Interrupt priority */

#define EnableIntCRC                    asm("BSET IEC4,#3")
#define DisableIntCRC                   asm("BCLR IEC4,#3")
#define SetPriorityIntCRC(priority)     (IPC16bits.CRCIP = priority)


/* 
   Macro to Clear CRC Interrupt Status bit
*/
#define CRC_Clear_Intr_Status_Bit()         (IFS4bits.CRCIF = 0)

/* 
   Macro to Return FIFO Full Status bit
*/
#define Get_CRC_FIFO_FULL_STATUS()            (UINT8)(CRCCONbits.CRCFUL)

/* 
   Macro to Return FIFO Empty Status bit
*/
#define Get_CRC_FIFO_EMPTY_STATUS()           (UINT8)(CRCCONbits.CRCMPT)

/* 
   Macro to Start CRC Calculation
*/
#define Start_CRC_Calulation()                (CRCCONbits.CRCGO = 1)       

/* 
   Macro to Stop CRC Calculation
*/
#define Stop_CRC_Calulation()                 (CRCCONbits.CRCGO = 0)       


/******************************************************************************
 * Function:        UINT16 CRC_Calc_ChecksumWord(UINT16* data, UINT16 Number_of_words,
 *                                       UINT16 prev_CRC)
 *
 * PreCondition:    CRC Module must be configured   
 *
 * Input:           data - Pointer to the first data word for which CRC needs to be 
 *                         calculated.
 *                  Number_of_words - Total number of words for which CRC needs to be 
 *                         calculated.
 *                  prev_CRC - previous CRC result. Note*
 *                  
 * Output:          Returns Two Byte CRC checksum based on the set polynomial
 *
 * Side Effects:    None
 *
 * Overview:        This function calculates CRC checksum for the data provide by the user,
 *                  based on the polynomial set in the CRCXOR Register.
 *
 * Note:            This input parameter is provided as a provision to allow continuation
 *                  of previously being computed checksum. In case the checksum is being calculated
 *                  for a fresh set of data then the input value for prev_CRC should be '0'.
 *****************************************************************************/
extern UINT16 CRC_Calc_ChecksumWord(UINT16* data, UINT16 Number_of_words, UINT16 prev_CRC) __attribute__ ((section (".libperi")));

/******************************************************************************
 * Function:        UINT16 CRC_Calc_ChecksumByte(UINT8* data, UINT16 Number_of_bytes,
 *                                       UINT16 prev_CRC)
 *
 * PreCondition:    CRC Module must be configured   
 *
 * Input:           data - Pointer to the first data byte for which CRC needs  
 *                         to be calculated.
 *                  Number_of_bytes - Total number of bytes for which CRC needs 
 *                         to be calculated.
 *                  prev_CRC - previous CRC result. Note*
 *                  
 * Output:          Returns One Byte CRC checksum based on the set polynomial
 *
 * Side Effects:    None
 *
 * Overview:        This function calculates CRC checksum for the data provide by ,
 *                  the user based on the polynomial set in the CRCXOR Register.
 *
 * Note:            This input parameter is provided as a provision to allow continuation
 *                  of previously being computed checksum. In case the checksum is being calculated
 *                  for a fresh set of data then the input value for prev_CRC should be '0'.
 *****************************************************************************/
extern UINT16 CRC_Calc_ChecksumByte(UINT8* data, UINT16 Number_of_bytes, UINT16 prev_CRC) __attribute__ ((section (".libperi")));

/******************************************************************************
 * Function:        void CRC_Config(UINT16 poly , UINT16 config)
 *
 * PreCondition:    None   
 *
 * Input:           poly - Polynomial to calculate CRC
 *                  config - CRC Control reg value
 *                  
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function configures CRC module
 *
 * Note:            None
 *****************************************************************************/
extern void CRC_Config(UINT16 poly , UINT16 config) __attribute__ ((section (".libperi")));


/******************************************************************************
 * Function:        void CRC_Config_INTR(UINT8 intr_byte)
 *
 * PreCondition:    None   
 *
 * Input:           intr_byte - Interrupt priority/State
 *                              bit 0 -  bit 2 --> priority setting
 *                                       bit 3 --> Interrupt Enable/Disable
 *                              bit 4 -  bit 7 --> unsused
 *                  
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function configures interrupts of CRC module
 *
 * Note:            None
 *****************************************************************************/
extern void CRC_Config_INTR(UINT8 intr_byte) __attribute__ ((section (".libperi")));

#else
#warning "Does not build for _CRC_PROG_V1"
#endif /* _CRC_PROG_V1 */

#endif  /* __CRC_H */
