/* Version 1: Base version                                               */
/* Version 2: Reduced PWU time-out to ~1 sec                             */
/* Version 3: Replaced X-reading with VReg ADC conversion                */
/* Version 4: Debugged                                                   */
/* Version 5: Send only RAW + Vreg as measured with BANDGAP as reference */
/* Version 7: Turn LF pins on and back off.                              */
/* Version 6: Send compensated data again.                               */
/* Version 8: Use LF as trigger for RF.                                  */
/* Version 9: Merge of versions 7 and 8 (RF frame now looks like v.7).   */
/* Version 11: Options for Suzuka/TPMS7 regarding LF conf (diff targets) */
/* Version 12: GPIO outputs modified as per updated EMC test layout and  */
/*             compatibility with application's settings.                */
/* Version 13: GPIO outputs modified again as per yet another updated    */
/*             EMC plan. LF sensitivity changed from LS to HS.           */

#define VERSION     ((UINT8)13u)
#define PTB1_WHEN_SUCCESS

/******************************************************************************
 * 
 * TPMS FXTH87 MKW01 LF TRIGGERED Rev1
 * RF Frame transmission is triggered by LF (125kHz)
 * The RF frame format and RF settings are compatible with the MKW01 receiver,
 * refer to MKW01_IAR7v4_Project_TPMS projects in particular. 
 * 
 ******************************************************************************/


/*
 ******************************************************************************
 *
 *  Main.c - Code will reside in here.
 *
 ******************************************************************************
 */
#include <hidef.h>                   /* for EnableInterrupts macro       */
#include "derivative.h"              /* include peripheral declarations  */
#include "main.h"                    /* reference to all Suzuka calls    */
#include "dal.h"                     /* reference to all Suzuka calls    */
#include "szk_lf_data_detect.h"
#include "szk_ff_tpm.h"


/* Globals going into PARAM registers */
#pragma CONST_SEG VERSIONING_ROM
const UINT16 cu16Freq = FREQ;
const UINT8  cu8Version = VERSION;
#pragma CONST_SEG DEFAULT

#pragma DATA_SEG BATTERY_BACKED_RAM
UINT16 gu16UUMA[5u];
UINT8  u8MainExeCnt;
UINT16 FrameID;
UINT32 Tire_ID;

#pragma DATA_SEG DEFAULT
UINT8  gu8CompPressure; /* 8-bit representation for comp pressure */
UINT8  gu8CompVolt;     /* Comp V */
UINT8  gu8CompTemp;     /* Comp T */
UINT8  gu8CompX;        /* 8-bit representation for comp X */
UINT8  gu8CompZ;        /* 8-bit representation for comp Z */
UINT16 u16CompPressure; /* 16-bit representation for comp P */
UINT16 u16CompAccelX;   /* 16-bit representation for comp X */
UINT16 u16CompAccelZ;   /* 16-bit representation for comp Z */
UINT8  u8StatusAcq;     /* Status byte for all measurements */
UINT16 gau16VReg[2];


/****************************************************************
 * 
 * Tire ID Selection
 * 
 ***************************************************************/
 
#define ID1 0xAA01AA01
#define ID2 0xBB02BB02
#define ID3 0xCC03CC03
#define ID4 0xDD04DD04

#define METHOD_FIXED_ID		0
#define METHOD_CYCLING_ID 	1		// ID changes each time a new frame is sent

/****************************************************************
 * 
 * Frame display selection
 * Choose here the way frames will be displayed on the MKW01 receiver side:
 * using the hyperterminal or the Freescale Sensor GUI.
 * Or the selection can be done in the MKW01 project.
 * 
 ****************************************************************/
/* Uncomment one of the defines */
//#define Frame_Display		0x11	/* When received by the MKW01, frame will be displayed using the HYPERTERMINAL */
#define Frame_Display		0x22	/* When received by the MKW01, frame will be displayed using the SENSOR GUI */
//#define Frame_Display		0x00   /* The choice of the display is done in the MKW01 project */

/****************************************************************
 * 
 * Data verification selection 
 * 
 ****************************************************************/

#define VERIFICATION_CRC_MKW01			1		// On the MKW01 side, a CRC verification will be done
#define VERIFICATION_CRC_FXTH			0		// On the MKW01 side, a CRC verification will be done
#define VERIFICATION_CHECKSUM			0		// On the MKW01 side, a CRC verification will be done
#define VERIFICATION_NO_VERIFICATION	0		// On the MKW01 side, a CRC verification will be done


/*
 ******************************************************************************
 *
 *                        M A I N
 *
 ******************************************************************************
 */
#pragma CODE_SEG DEFAULT
void main(void) 
{
  UINT8 u8LFCount;
  UINT8 u8LFFirst;
  
  u8LFFirst = LFDATA;

  
  /* Config GPIO for setup */
  vfnSetupGPIO();
 
  for(;;)
  {
    
    if(CLEAR == SPMSC2_PDF)
    {
      /* Set PWU, enable STOP, disable RF */
      vfnSetupMCU();
      vfnSetPWU();    
      /* Determine derivative once */
      (void)u8fnDALDetectDerivative();
      
      /* Clear the interrupts flag */
      TPMS_INTERRUPT_FLAG = CLEAR;
      
      FrameID = CLEAR;
      
      /* Configure LFR for data mode */
      vfnDataModeInit();
      vfnClearReceivedBuffer();
      TPMS_LF_ENABLE(SET);
    }
    else
    {
      EnableInterrupts;

      if(SET == SIMSES_LFF)
      {
        SIMOPT1 = SIMOPT1_STOPE_MASK | SIMOPT1_BKGDPE_MASK | BIT0;
        vfnSetSTOPMode(STOP4);
#ifdef DEBUGGING_CODE_NOW
        PTADD = 0x1F;
        PTAD  = 0x1F;
#endif
        u8LFCount = TPMS_LF_READ_DATA(gau8DataBuffer, sizeof(gau8DataBuffer));
#ifdef DEBUGGING_CODE_NOW
        PTAD = 0x1F;
#endif
        
        TPMS_LF_ENABLE(CLEAR);
        
        TPMS_INTERRUPT_FLAG = CLEAR;
        
        vfnSetSTOPMode(STOP4);
        
        gau8DataBuffer[CLEAR] = u8LFFirst;
        
        if(SET == u8fnDataValidData())
        {
#ifdef PTB1_WHEN_SUCCESS 
          PTBDD = PTBDD_PTBDD1_MASK;
          PTBD  = PTBD_PTBD1_MASK;
#endif
          Measure_P_T_V_AccZ();
          TPMS_RF_ENABLE(SET);
          vfnWaitMSec(3u);
          
          Init_RF(); 
          
#if (METHOD_FIXED_ID)
   /* Uncomment one of the four IDs */
	Tire_ID = ID1;
	//Tire_ID = ID2;
	//Tire_ID = ID3;
	//Tire_ID = ID4;
#elif (METHOD_CYCLING_ID)
	switch (Tire_ID){
	case (ID1): Tire_ID = ID2;
	break;
	
	case (ID2): Tire_ID = ID3;
	break;
	
	case (ID3): Tire_ID = ID4;
	break;
	
	case (ID4): Tire_ID = ID1;
	break;
	
	default: Tire_ID = ID1;	
	}
#endif
          RFCR7_RFIACK = SET;  // Clear all Flags
          
          Fill_RFBUFFER();
          TPMS_RF_SET_TX(255); 
#ifdef PTB1_WHEN_SUCCESS 
          PTBD  = CLEAR;
#endif
        }
        else
        {
#ifdef DEBUGGING_CODE_NOW
          PTADD = 0x1F;
          PTAD  = 0x4;
#endif
          /* Wait 4 msec for LF to turn off */
          vfnWaitMSec(4u);
          /* Wait an additional 20 msec to avoid catching the same frame again */
          vfnWaitMSec(20u);
          
          vfnDataModeInit();
          TPMS_LF_ENABLE(SET);
#ifdef DEBUGGING_CODE_NOW
          PTAD = CLEAR;
#endif
        }
        
      }
      else if(SET == SIMSES_RFF)
      {
#ifdef DEBUGGING_CODE_NOW
        PTADD = 0x1F;
        PTAD  = 0x2;
#endif
        vfnSetupMCU();
        vfnSetSTOPMode(STOP4);
        TPMS_RF_ENABLE(CLEAR);
        /* Configure LFR for data mode */
        vfnDataModeInit();
        vfnClearReceivedBuffer();
        TPMS_LF_ENABLE(SET);
        vfnWaitMSec(3);
#ifdef DEBUGGING_CODE_NOW
        PTAD = CLEAR;
#endif
      }
      else
      {
#ifdef DEBUGGING_CODE_NOW
        PTADD = 0x1F;
        PTAD  = 0x8;
#endif
        vfnSetupMCU();
        vfnSetSTOPMode(STOP4);
#ifdef DEBUGGING_CODE_NOW
        PTAD = CLEAR;
#endif
      }
      
      /* Clear STOP1 entry flag */
      SPMSC2_PPDACK = SET;
    } /* End PDF is set */
    
    
    u8MainExeCnt++;
    vfnSetSTOPMode(STOP1);
    __asm STOP;
    
    
    /* Safety net */
  }
}
/******************************************************************************

function    :Init_RF(void)

parameters  :void

returns     :void

type        :low level c

description: RF Setup 

*******************************************************************************/

void Init_RF(void)
{  
  /* Turn module on in case it wasn't */
  TPMS_RF_ENABLE(SET);

  /* In this example registers are configured by hand. Could also be */
  /* done through TPMS_RF_CONFIG().                                  */
    RFCR0=0x19;
    
    RFCR1=0x78;    // set to 78 for 120 bits - largest frame
    
    RFCR2=0x0E;    // RF Transmission OFF - No EOM - Pout=5dBm    - RPAGE=0
                   // 00001110   

    RFCR3=0x00;    // RF Output Low - RF Power UP - One Frame Transmitted
                   // 00000000
    
    RFCR4=0x01;     //Interframe timing set to 1
   
    RFCR5=0x00;     //No Pseudo-random number used
   
    RFCR6=0x01;     //VCO highest Power - interframe timing
                    // was 00
    //r20246 was 0x00
    RFCR7=0x08;     // RF Interrupt Disable - LVD Disable - RFM Not reset
                    
#if(FREQ==315)
   PLLCR0=0x1C;   //  00011100
                     
   PLLCR1=0xD2;   
                     
 
   //  315M+50K --> d950 --->0001110110110
   
   PLLCR2=0x1D;   //  00011101
                    
   PLLCR3=0xB2;   //  10110  010
#elif(FREQ==434)     
   
   PLLCR0=0xB0;   // 10110000
                      
   PLLCR1=0x62;
                     
 
   //  434M+35K --> d5682 --->1011000110010
   
   PLLCR2=0xB1;   // 10110001
                      
   PLLCR3=0x56;   // 01010   110 CF=1  (bit2)
#endif    

  return;
}

/****************************************************************************
Function	:	delay
NOTES		:	realise un delay
*****************************************************************************/

void delay(UINT8 r_max)
{
  UINT8 r,q;
  for(r=0; r<r_max; r++)
  {
  	for(q=0; q<16; q++)
  	{
  	  /* Stay here for a bit */
  	}
  }
  
  return;
} 
/****************************************************************************
Function	: Measure_P_T_V
NOTES		:   This function measures Pressure, Temperature, Voltage and store them in RFRD_data

*****************************************************************************/
void Measure_P_T_V_AccZ(void)
{                                                                    
   UINT8 u8ZIndex;
   
   /* Enable Bandgap - required for V and T measurements */
   SPMSC1_BGBE = SET;
   
   vfnWaitMSec(5u);
   
   u8StatusAcq=0;
    
   /****Initial measurements for compensation ***/  
   u8StatusAcq |= TPMS_READ_VOLTAGE(gu16UUMA);
   u8StatusAcq |= TPMS_READ_TEMPERATURE(gu16UUMA);
   /****Pressure data acquisition ***/  
   u8StatusAcq |= TPMS_READ_PRESSURE(gu16UUMA, 4u);    
  // gu16UUMA[2]+=256; //Offset to avoid to flag under pressure 350kPa approx.                                      
   u8StatusAcq |= TPMS_COMP_PRESSURE(&u16CompPressure, gu16UUMA);     
   gu8CompPressure = (UINT8)(u16CompPressure>>1);
   /****Temperature data acquisition ***/  
   u8StatusAcq |= TPMS_COMP_TEMPERATURE(&gu8CompTemp, gu16UUMA);        
   /****Voltage data acquisition ***/  
   u8StatusAcq |= TPMS_COMP_VOLTAGE(&gu8CompVolt, gu16UUMA);    
   
   /* gu8Derivative is owned by DAL. It allows us to differentiate between */
   /* a one-axis and a two-axis product. Here, we use that info to make    */
   /* a smart decision of whether to read the X-axis or not.               */
   if(TWO_AXIS_DERIVATIVE_INDEX == gu8Derivative) 
   {
     u8StatusAcq|=TPMS_READ_ACCEL_X(gu16UUMA, 1u, CLEAR, 7u);
     u8StatusAcq|=TPMS_COMP_ACCEL_X((UINT16*)&u16CompAccelX, gu16UUMA);
     gu8CompX = (UINT8)(u16CompAccelX>>1);
     
     u8ZIndex = ((UINT8)6u); //7: Nogaro / Lausitz / Suzuka
                             //6: Melbourne
   } 
   else 
   {
    u8ZIndex = ((UINT8)6);
   }
   
   /* No matter the derivative, always take Z-axis readings */
   u8StatusAcq |= TPMS_READ_ACCEL_Z(gu16UUMA, 1u, CLEAR, u8ZIndex);
   u8StatusAcq |= TPMS_COMP_ACCEL_Z((UINT16*)&u16CompAccelZ, gu16UUMA);
   gu8CompZ = (UINT8)(u16CompAccelZ>>1);
   
   /* Disable bandgap - allows us to save some power */
   SPMSC1_BGBE = CLEAR;
         
   return;       
}

/******************************************************************************

function    :Fill_RFBUFFER(void)

parameters  :void

returns     :void

type        :low level c

description: RF Buffer filling 

*******************************************************************************/
void Fill_RFBUFFER(void)
{
	
	UINT8  au8RFDataForCS[32]; // Maximum length is 32 bytes; size of the RF buffer (in bytes)
	UINT8 Payload_Length;
	UINT8 Receiver_Address;
	UINT8 Verification_Type; 
	UINT16 Verification_Value;
	Payload_Length = 0x18; // Value updated below in case of MKW01 CRC
	Receiver_Address = 0xFF; // Must match the MKW01 address
	
	/* Verification type => to be chosen at the beginning of the main; do not modify the value here */
	Verification_Type = 0x00; // Value updated below; 0x03 => MKW01 CRC, 0x02 => TPMS CRC, 0x01 => Checksum, 0x00 => no verification

	
	/* Gather data into a local array that is to be loaded into the RF */
	
	au8RFDataForCS[0u] =  (UINT8)(0x55); 					// Preamble
	au8RFDataForCS[1u] =  (UINT8)(0x55); 					// Preamble
	au8RFDataForCS[2u] =  (UINT8)(0x55); 					// Preamble
	au8RFDataForCS[3u] =  (UINT8)(0x01); 					// Sync word 
	au8RFDataForCS[4u] =  (UINT8)(0x01); 					// Sync word 
	au8RFDataForCS[5u] =  (UINT8)(0x01);				    // Sync word
	au8RFDataForCS[6u] =  (UINT8)(0x01);				    // Sync word
	au8RFDataForCS[7u] =  (UINT8)(Payload_Length); 			// Payload length, 0x18=24 bytes 
	au8RFDataForCS[8u] =  (UINT8)(0xF0); 					// MKW01 receiver address (NODE_ADDRESS 0xF0 or BROADCAST_ADDRESS 0xFF)
	au8RFDataForCS[9u] =  (UINT8)(Tire_ID >> 24u); 			// Tire ID
	au8RFDataForCS[10u] = (UINT8)(Tire_ID >> 16u); 			// Tire ID
	au8RFDataForCS[11u] = (UINT8)(Tire_ID >> 8u); 		   	// Tire ID
	au8RFDataForCS[12u] = (UINT8)(Tire_ID);       			// Tire ID
	au8RFDataForCS[13u] = (UINT8)(u16CompPressure >> 8u); 	// Pressure
	au8RFDataForCS[14u] = (UINT8)(u16CompPressure);
	au8RFDataForCS[15u] = (UINT8)(u16CompAccelZ >> 8u); 	// Z-axis acceleration
	au8RFDataForCS[16u] = (UINT8)(u16CompAccelZ);	  
	au8RFDataForCS[17u] = (UINT8)(u16CompAccelX >> 8u); 	// X-axis acceleration
	au8RFDataForCS[18u] = (UINT8)(u16CompAccelX);
	au8RFDataForCS[19u] = (UINT8)(gu8CompVolt); 			// Voltage
	au8RFDataForCS[20u] = (UINT8)(gu8CompTemp); 			// Temperature
	au8RFDataForCS[21u] = (UINT8)(u8StatusAcq); 			// Status Acquisition
	au8RFDataForCS[22u] = (UINT8)(FrameID >> 8); 			// Frame ID: keep alive counter 
	au8RFDataForCS[23u] = (UINT8)(FrameID);
	au8RFDataForCS[24u] = (UINT8)(Verification_Type); 		// Verification Type: MKW01 CRC, FXTH CRC, checksum or no verification
	au8RFDataForCS[25u] = (UINT8)(Frame_Display);			// Frame display: hyperterminal, Sensor GUI or selection to be done on the MKW01 side
	au8RFDataForCS[26u] = (UINT8)(0xC1); 					// Fixed data => can be modified by the user
	au8RFDataForCS[27u] = (UINT8)(0xC2); 					// Fixed data => can be modified by the user
	au8RFDataForCS[28u] = (UINT8)(0xC3); 					// Fixed data => can be modified by the user
	au8RFDataForCS[29u] = (UINT8)(0xC4); 					// Fixed data => can be modified by the user

	
#if (VERIFICATION_CRC_MKW01)
		Payload_Length -= 2; // MKW01 CRC is not part of the payload (refer to MKW01 RM)
		au8RFDataForCS[7u] =  (UINT8)(Payload_Length);	
		
		Verification_Type = 0x03;
		au8RFDataForCS[24u] = (UINT8)(Verification_Type);
	
		Verification_Value = Calculate_CRC_MKW01( &au8RFDataForCS[7], (UINT8)(Payload_Length + 1));		
		
#elif (VERIFICATION_CRC_FXTH)
		Verification_Type = 0x02;
		au8RFDataForCS[24u] = (UINT8)(Verification_Type);
		
		Verification_Value = TPMS_CRC16(&au8RFDataForCS[7],(Payload_Length - 1), 0);
		
#elif (VERIFICATION_CHECKSUM)
		Verification_Type = 0x01;
		au8RFDataForCS[24u] = (UINT8)(Verification_Type);
		
		Verification_Value = 0xC5 << 8;
		Verification_Value &= 0xFF00;
		Verification_Value |= CheckSum_FSL_Full(&au8RFDataForCS[7], (Payload_Length - 1));
		
#else
		Verification_Value = 0xC5C6; /* Fixed data; no verification will be done on the MKW01 side */
#endif
 	

		au8RFDataForCS[30u] = (UINT8)(Verification_Value>>8);  // CRC, checksum or fixed data
		au8RFDataForCS[31u] = (UINT8)(Verification_Value);
		
	 TPMS_RF_WRITE_DATA_REVERSE(sizeof(au8RFDataForCS), &(au8RFDataForCS[0]),0u);
}
 


 /****************************************************************************/
 /* Function	: CheckSum_FSL_Full(byte *array)                               */
 /* NOTES		:	     Compute checkusum - has to be complient to ESTAR receiver */
/*****************************************************************************/

UINT8 CheckSum_FSL_Full(UINT8 *array, UINT8 u8Size)
{
  UINT8 j;
  UINT8 u8CS;
  
  u8CS = CLEAR;
  
  for(j = 0; j < u8Size; j++)
  {
    u8CS += *(array++);
  }
  u8CS = ((UINT8)0xFFu) - u8CS;
  return(u8CS);
}
/*
 ******************************************************************************
 * u16fnAccessUUMA
 ******************************************************************************
 */
UINT16 u16fnAccessUUMA(UINT8 u8Index)
{
  UINT16 u16Result;
  
  u16Result = CLEAR;
  switch(u8Index)
  {
    case(0u):
    {
      u16Result = gu16UUMA[UUMA_VOLT];
      break;
    }
    case(1u):
    {
      u16Result = gu16UUMA[UUMA_TEMP];
      break;
    }
    case(2u):
    {
      u16Result = gu16UUMA[UUMA_PRESSURE];
      break;
    }
    case(3u):
    {
      u16Result = gu16UUMA[UUMA_X];
      break;
    }
    case(4u):
    {
      u16Result = gu16UUMA[UUMA_Z];
      break;
    }
    default:
    {
      u16Result = CLEAR;
    }
  };
  
  return(u16Result);
}
/*
 ******************************************************************************
 *
 *                        vfnSetupMCU
 *
 ******************************************************************************
 */
void vfnSetupMCU(void)
{
   /* enable bandgap for V, T measurements, enable stop4 mode */   
  SPMSC1  = SPMSC1_BGBE_MASK | SPMSC1_LVDE_MASK | SPMSC1_LVDSE_MASK;
  
  /* enable STOP mode, Enable RFM, disable COP - A real app will need COP */
  SIMOPT1 = (SIMOPT1 | SIMOPT1_STOPE_MASK)  & (UINT8)(~((UINT8)SIMOPT1_COPE_MASK));
  
  return;
}
/*
 ******************************************************************************
 *
 *                        vfnSetSTOPMode
 *
 ******************************************************************************
 */
void vfnSetSTOPMode(UINT8 u8Mode)
{
  /*
  Table 3-1. Stop Mode Selection
  SIMPOT1  SPMSC2   SPMSC1        BDCSCR
  STOPE    PDC      LVDE & LVDSE  ENBDM   Stop Mode
    0       x        x             x      Stop modes disabled; illegal opcode reset if STOP instruction executed
    1       1        0             0      Stop1
    1       x        1             x      Stop4
    1       x        x             1      Stop4 with BDM
  */  
  if (u8Mode == STOP1)
  {
    SPMSC2 |= SPMSC2_PDC_MASK;
    SPMSC1 = (SPMSC1 | SPMSC1_LVDE_MASK) & (UINT8)(~((UINT8)(SPMSC1_LVDSE_MASK | SPMSC1_BGBE_MASK)));
  }
  else if (u8Mode == STOP4)
  {
    SPMSC2 |= SPMSC2_PDC_MASK;
    /* Use BGBE for accurate ADC measurements */
    SPMSC1 |= (SPMSC1_LVDSE_MASK | SPMSC1_LVDE_MASK | SPMSC1_BGBE_MASK); 
  }
  else
  {
    /* Do nothing */
  }
}
/*
 ******************************************************************************
 *
 *                        vfnSetPWU
 *
 ******************************************************************************
 */
void vfnSetPWU(void)
{
  /* Configure PWU for a periodic wake-up (~1 sec) */
  PWUCS0 = 0x1Fu;
  PWUCS1 = CLEAR;
  PWUDIV = 0x1Fu;
  
  return;
}

/*
 ******************************************************************************
 *  vfnSetupGPIO
 ******************************************************************************
 */
void vfnSetupGPIO(void)
{
  /* On 28-May-2014, this function has been modified to match Pascal       */
  /* Bernard's request through e-mail, which follows. This is for v.13     */
  /* 1/ GPIO                                                               */
  /* PTA0 Output low                                                       */
  /* PTA1 Input                                                            */
  /* PTA2 Output High                                                      */
  /* PTA3 Output low                                                       */
  /* PTB0 Output low                                                       */
  /* PTB1 Toggle LF                                                        */

  PTAD  = PTA2_IS_HIGH;
  PTADD = (PTADD_PTADD0_MASK | PTADD_PTADD2_MASK | PTADD_PTADD3_MASK);
  
  PTBD  = CLEAR;
  PTBDD = ALL_PTBS_ARE_OUTPUT;
  
  return;
}

/* Added for MKW01 CRC */

UINT16 Calculate_CRC_MKW01( UINT8 *buffer, UINT8 length)
{
	UINT8 i = 0;
	UINT16 crc = 0;
	UINT16 polynomial = 0;
	polynomial = 0x1021;
	crc = 0x1D0F;
	for( i = 0; i < length; i++ )
	{
		crc = ComputeCrc_MKW01( crc, buffer[i], polynomial );
	}
		return( ( UINT16 ) ( ~crc ));
}

UINT16 ComputeCrc_MKW01( UINT16 crc, UINT8 dataByte, UINT16 polynomial )
{
	UINT8 i;
	for( i = 0; i < 8; i++ )
	{
		if( ( ( ( crc & 0x8000 ) >> 8 ) ^ ( dataByte & 0x80 ) ) != 0 )
		{
			crc <<= 1; // shift left once
			crc ^= polynomial; // XOR with polynomial
		}
		else
		{
			crc <<= 1; // shift left once
		}
		dataByte <<= 1; // Next data bit
	}
	return crc;
}


/*
 ******************************************************************************
 *
 *  End of file.
 *
 ******************************************************************************
 */
