PDA

View Full Version : help em voi anh em oi giai thich dum em doan code cua con em4095


vinh172001
22-06-2012, 01:33 PM
/////////////////////////////////////////////////////////////////////////
//// em4095.c ////
//// This file contains drivers for a EM4095 RFID basestation. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// Pin Layout ////
//// ------------------------------------------------------------ ////
//// | | ////
//// | 1: VSS GND | 16: DC2 | ////
//// | | | ////
//// | 2: RDY/CLK RF_RDY_CLK | 15: FCAP | ////
//// | | | ////
//// | 3: ANT1 | 14: SHD RF_SHD | ////
//// | | | ////
//// | 4: DVDD | 13: DEMOD_OUT RF_DEMOD_OUT | ////
//// | | | ////
//// | 5: DVDS | 12: MOD RF_MOD | ////
//// | | | ////
//// | 6: ANT2 | 11: AGND | ////
//// | | | ////
//// | 7: VDD +5V | 10: CDEC_IN | ////
//// | | | ////
//// | 8: DMOD_IN | 9: CDEC_OUT | ////
//// ------------------------------------------------------------ ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2004 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////

#ifndef EM4095
#define EM4095

#ifndef RF_SHD
#define RF_RDY_CLK PIN_C0 // External interrupt used to read clock
#define RF_SHD PIN_B1 // High disables the antenna signal
#define RF_MOD PIN_B2 // High does 100% modulation
#define RF_DEMOD_OUT PIN_C2 // Data read in interrupt service routine
#endif


// Provide a buffer for storing recieved data and data to be sent
#define RFBUFFER_SIZE 20
int8 RFbuffer[RFBUFFER_SIZE];
int8 RFbuffer_index = 0;
int8 RFbuffer_bitIndex = 0;
#define END_OF_RFBUFFER (RFbuffer_index == sizeof(RFbuffer))


/////////////////////////////////////////////////////////////////////////
//// Read modes available for reading data from a transponder
/////////////////////////////////////////////////////////////////////////
int8 RF_readMode;
#define RF_MANCHESTER_DATA 0 // Reads Manchester encoded data
#define RF_MEASURE_WIDTHS 1 // Measure a series of widths
#define RF_FIND_WIDTH 2 // Find a specific width
#define RF_FIND_PATTERN 3 // Find a pattern of widths
/////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////
//// Global Variables
/////////////////////////////////////////////////////////////////////////
int1 bitValue = 1;
int1 storeData = TRUE;
int1 RE_FE_TOGGLE = 1;
int1 RF_widthFound = FALSE;
int1 RF_patternFound = FALSE;
int8 RF_widthToFind = 0;
int8* RF_findWidths = 0;
int8 RF_uncertainty = 0;
int8 timer0_overflows = 0;
int8 dataTransferred = 0;
int16 old_clock = 0;
/////////////////////////////////////////////////////////////////////////


// Purpose: Initializes the 4095 into sleep mode
// Sets up the timers and interrupts
void rf_init()
{
output_low(RF_SHD);
output_low(RF_MOD);

setup_timer_1(T1_EXTERNAL_SYNC | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_RE);
setup_ccp2(CCP_COMPARE_INT);

setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
}

// Purpose: Powers down the RF antenna
#define rf_powerDown() output_high(RF_SHD);

// Purpose: Powers up the RF antenna
#define rf_powerUp() output_low(RF_SHD);


// Purpose: Select which edge to begin reading data
void RF_readEdge(int1 edge)
{
if(edge)
{
setup_ccp1(CCP_CAPTURE_RE);
RE_FE_TOGGLE = 1;
}
else
{
setup_ccp1(CCP_CAPTURE_FE);
RE_FE_TOGGLE = 0;
}
}


// Purpose: Interrupt service routine to handle compare 1 interrupts.
// Reads incoming data from a transponder and stores it in
// the global buffer.
#INT_CCP1
void isr_ccp1()
{
int8 width;

// Toggle between capturing rising and falling edges to meausure width
if(RE_FE_TOGGLE)
{
setup_ccp1(CCP_CAPTURE_FE);
RE_FE_TOGGLE = 0;
}
else
{
setup_ccp1(CCP_CAPTURE_RE);
RE_FE_TOGGLE = 1;
}

// Calculate the width
width = CCP_1 - old_clock;
old_clock = CCP_1;

switch(RF_readMode)
{
// Use to receive manchester formatted data from a transponder
case RF_MANCHESTER_DATA:
{
if(width > 54) // Check for a phase change
{
bitValue = ~bitValue; // Invert the save bit value
storeData = TRUE; // Force a bit store
}

if(storeData)
{
shift_right(RFbuffer+RFbuffer_index, 1, bitValue);
++dataTransferred;

if(++RFbuffer_bitIndex == 8)
{
RFbuffer_bitIndex = 0;
++RFbuffer_index;
}
}

storeData = ~storeData;
break;
}

// Use to read high and low widths
case RF_MEASURE_WIDTHS:
{
RFbuffer[RFbuffer_index++] = width;
++dataTransferred;

break;
}

// Use to search for a certain pulse width
case RF_FIND_WIDTH:
{
if(width > (RF_widthToFind - RF_uncertainty)
&& width < (RF_widthToFind + RF_uncertainty))
{
RF_widthFound = TRUE;
}
break;
}

case RF_FIND_PATTERN:
{
if(width > RF_findWidths[RFbuffer_index] - RF_uncertainty
&& width < RF_findWidths[RFbuffer_index] + RF_uncertainty)
{
if(++RFbuffer_index == dataTransferred)
{
RF_patternFound = TRUE;
}
}
else
{
if(RFbuffer_index > 0)
{
int8 pos, i, j;
pos = RFbuffer_index-1; // Save the initial position

// Try to match partial pattern
while(--RFbuffer_index != 0)
{
if(width > RF_findWidths[RFbuffer_index] - RF_uncertainty
&& width < RF_findWidths[RFbuffer_index] + RF_uncertainty)
{
for(i=pos, j=RFbuffer_index-1; j!=255; --i, --j)
{
if(RF_findWidths[j] != RF_findWidths[i])
{
break;
}
}
if(j == 255)
{
break;
}
}
}
}
}
break;
}
}
}


// Purpose: This interrupt service routine is used
// to send data to a transponder
// Inputs: None
// Outputs: None
#INT_CCP2
void isr_ccp2()
{
static int1 mode = 1;

if(mode == 1 && !END_OF_RFBUFFER)
{
// Output high to modulate the antenna, so send a 0 with modulation pin high
output_bit(RF_MOD, !bit_test(RFbuffer[RFbuffer_index], RFbuffer_bitIndex));

if(++RFbuffer_bitIndex == 8) // Increment the buffer indexes as necessary
{
RFbuffer_bitIndex = 0;
++RFbuffer_index;
}

CCP_2 += 30; // Wait for half the bit period minus two RF periods
mode = 0; // Toggle the mode
}
else
{
output_low(RF_MOD); // No modulation
CCP_2 += 34; // Wait for half the bit period plus 2 RF periods before sending another bit
++dataTransferred; // Increment the bits transferred counter
mode = 1; // Toggle the mode
}
}


// Purpose: Interrupt for timer 0. Keeps track of the number of
// overflows for timeouts.
// Inputs: None
// Outputs: None
#INT_RTCC
void isr_rtcc()
{
++timer0_overflows;
}


// Purpose: Fill the buffer with data read from the basestation
// Inputs: 1) The number of bits to read
// 2) TRUE start on rising edge
// FALSE start on falling edge
// Outputs: The number of bits read. Could be used to check for timeout
int8 RF_get(int8 numBits, int1 edge)
{
RF_readEdge(edge);
RF_readMode = RF_MANCHESTER_DATA;

storeData = TRUE;
bitValue = 0;
RFbuffer_index = 0;
RFbuffer_bitIndex = 0;
dataTransferred = 0;
timer0_overflows = 0;
old_clock = 0;
set_timer1(0);

clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
while(dataTransferred < numBits && timer0_overflows < 15);
disable_interrupts(INT_CCP1);

RFbuffer_index = 0;
RFbuffer_bitIndex = 0;

return dataTransferred;
}


// Purpose: Send data from the buffer to the transponder
// Inputs: 1) Send numBits of data to the transponder
// 2) The index in the buffer to start at
// 3) The bit position at the index to start at
// Outputs: None
void RF_send(int8 numBits, int8 index, int8 bitPosition)
{
RFbuffer_index = index;
RFbuffer_bitIndex = bitPosition;
dataTransferred = 0;
CCP_2 = 3; //
set_timer1(0); // Cause an interrupt imediately

enable_interrupts(INT_CCP2);
while(dataTransferred < numBits);
disable_interrupts(INT_CCP2);
}


// Purpose: Search for a certain pulse width
// Inputs: 1) The width length in clocks
// 2) Uncertainty to search over a range
// 3) TRUE start on rising edge
// FALSE start on falling edge
// ex) numClocks = 128; uncertainty = 6; range = 122 to 134
// Outputs: TRUE if width was found, FALSE if not found
int1 RF_findWidth(int8 numClocks, int8 uncertainty, int1 edge)
{
RF_readEdge(edge);

RF_readMode = RF_FIND_WIDTH;
RF_widthToFind = numClocks;
RF_widthFound = FALSE;
RF_uncertainty = uncertainty;
timer0_overflows = 0;
old_clock = 0;
set_timer1(0);

clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
while(RF_widthFound == FALSE && timer0_overflows < 50);
disable_interrupts(INT_CCP1);

return RF_widthFound;
}


// Purpose: Measure a number of pulse widths, both high and low
// Inputs: 1) The number of widths to measure
// 2) TRUE start on rising edge
// FALSE start on falling edge
// Outputs: The number of widths that were measured. If there is
// no transponder in range, the timeout could occur.
int8 RF_measureWidths(int8 numWidths, int1 edge)
{
RF_readEdge(edge);

RF_readMode = RF_MEASURE_WIDTHS;
dataTransferred = 0;
RFbuffer_index = 0;
timer0_overflows = 0;
old_clock = 0;
set_timer1(0);

clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
while(dataTransferred < numWidths && timer0_overflows < 50);
disable_interrupts(INT_CCP1);

return dataTransferred;
}

// Purpose: Measure a number of pulse widths, both high and low
// Inputs: 1) A pointer to an array of widths. It is safe to use RFbuffer.
// 2) The number of widths in the pattern
// 3) Uncertainty to search over a range
// 4) TRUE start on rising edge
// FALSE start on falling edge
// Outputs: The number of widths that were measured. If there is
// no transponder in range, the timeout could occur.
int8 RF_findPattern(int8* widths, int8 numWidths, int8 uncertainty, int1 edge)
{
RF_readEdge(edge);

RF_readMode = RF_FIND_PATTERN;
RF_patternFound = FALSE;
RFbuffer_index = 0;
RF_findWidths = widths;
dataTransferred = numWidths;
RF_uncertainty = uncertainty;
timer0_overflows = 0;
old_clock = 0;
set_timer1(0);

clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
while(RF_patternFound == FALSE && timer0_overflows < 40);
disable_interrupts(INT_CCP1);

return RF_patternFound;
}


// Purpose: Set every byte in the buffer to data
// Inputs: None
// Outputs: None
void RFbuffer_fill(int8 data)
{
int i;

for(i=0; i<sizeof(RFbuffer); ++i)
{
RFbuffer[i] = data;
}
}


// Purpose: Inverts every byte in the buffer
// Inputs: None
// Outputs: None
void RFbuffer_invert()
{
int i;

for(i=0; i<sizeof(RFbuffer); ++i)
{
RFbuffer[i] = ~RFbuffer[i];
}
}


// Purpose: Get a bit of data from the buffer and increment to the next bit
// Inputs: None
// Ouputs: A bit of data
int1 RFbuffer_getBit()
{
int1 bit;

if(!END_OF_RFBUFFER)
{
bit = bit_test(RFbuffer[RFbuffer_index], RFbuffer_bitIndex);

if(++RFbuffer_bitIndex == 8)
{
++RFbuffer_index;
RFbuffer_bitIndex = 0;
}
}

return bit;
}


// Purpose: Get a byte of data from the buffer
// Inputs: None
// Outputs: The byte of data
int8 RFbuffer_getByte()
{
if(!END_OF_RFBUFFER)
{
int8 i;
int8 data;

for(i=0; i<8; ++i)
{
shift_right(&data, 1, RFbuffer_getBit());
}

return data;
}
}


// Purpose: Set the value of the next bit in the buffer
// Inputs: None
// Outputs: None
void RFbuffer_setBit(int1 bit)
{
if(!END_OF_RFBUFFER)
{
if(bit)
{
bit_set(RFbuffer[RFbuffer_index], RFbuffer_bitIndex);
}
else
{
bit_clear(RFbuffer[RFbuffer_index], RFbuffer_bitIndex);
}

if(++RFbuffer_bitIndex >= 8)
{
++RFbuffer_index;
RFbuffer_bitIndex = 0;
}
}
}

// Purpose: Set the value of the next byte in the buffer
// Inputs: None
// Outputs: None
void RFbuffer_setByte(int8 data)
{
if(!END_OF_RFBUFFER)
{
int8 i;
for(i=0; i<8; ++i)
{
RFbuffer_setBit(bit_test(data, 7));
rotate_left(&data, 1);
}
}
}

#endif




voi con em4102 ho em voi

/////////////////////////////////////////////////////////////////////////
//// EM4102.c ////
//// ////
//// This file contains drivers for a 4102 RF transponder ////
//// ////
//// int1 read_4102(int8* data) ////
//// - Call this funtion to read a 4102 transponder ////
//// - Pass in a pointer to a 5 byte array ////
//// - The first byte will have the customer code and the last ////
//// four bytes will contain the ID number ////
//// ////
//// - Returns FALSE if a parity check error occurred ////
//// - Returns TRUE if a transponder was read successfully ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2004 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////


#ifndef TRANSPONDER_4102_DRIVERS
#define TRANSPONDER_4102_DRIVERS

//#define UNIVERSAL_FORMAT

// Function Prototypes
int1 read_4102(int8* data);
int1 header_search_4102();
int1 decode_data_4102(int8* data);


// Purpose: Reads the ID number and data number
// Inputs: A pointer to a 5 byte array to fill
// * The first byte will have the ID
// * The last 4 bytes will have the data
// Outputs: TRUE if read successful, FALSE if read failed
int1 read_4102(int8* data)
{
int8 i;

RF_get(sizeof(RFbuffer)*8, TRUE); // Fill the buffer with data

for(i=0; i<2; ++i)
{
while(!END_OF_RFBUFFER)
{
if(header_search_4102()) // Try to find 9 consecutive 1s
{
if(decode_data_4102(data)) // Try to decode the data after the header
{
RFbuffer_fill(0xAA); // Prevents false detection

#ifdef UNIVERSAL_FORMAT
i=data[1];
data[1]=data[3];
data[3]=i;
i=data[0];
data[0]=data[4];
data[4]=i;
#endif

return TRUE; // Return sucessful read
}
}
}
RFbuffer_invert(); // Invert the buffer because the
} // Manchester encoded data could have
// been read starting at the wrong edge

RFbuffer_fill(0xAA); // Prevents false detection
return FALSE; // Return error
}


// Purpose: Search for the header consisting of 9 ones
// Inputs: None
// Outputs: TRUE if the header was found, FALSE if it was not found
int1 header_search_4102()
{
int bitCounter = 0;

// Loops until 9 consecutive 1s are found
// or the end of the receive buffer is reached
while(!END_OF_RFBUFFER)
{
if(RFbuffer_getBit() == 1)
{
if(++bitCounter == 9)
{
return TRUE;
}
}
else
{
bitCounter = 0;
}
}

return FALSE;
}


// Purpose: Decodes the ID number and data number
// Inputs: A pointer to a 5 byte array to fill
// * The first byte will have the ID
// * The last 4 bytes will have the data
// Outputs: TRUE if read successful, FALSE if read failed
int1 decode_data_4102(int8* data)
{
int1 bit = 0;
int8 count = 1;
int1 parity = 0;
int1 colParity1 = 0;
int1 colParity2 = 0;
int1 colParity3 = 0;
int1 colParity4 = 0;

// Loop until 40 bits of data and 10 bits of parity are received
for(count=1; count <= 50; ++count)
{
bit = RFbuffer_getBit();
if(END_OF_RFBUFFER)
{
return FALSE;
}

if(count % 5 == 0)
{
// Check for row parity
if(parity != bit)
{
return FALSE;
}
parity = 0;
}
else
{
// Store a bit of data
#ifdef UNIVERSAL_FORMAT
shift_left(data, 5, bit);
#else
shift_right(data, 5, bit);
#endif

// Calculate row parity
parity ^= bit;

// Calculate column parity
switch (count % 5)
{
case 1: colParity1 ^= bit; break;
case 2: colParity2 ^= bit; break;
case 3: colParity3 ^= bit; break;
case 4: colParity4 ^= bit; break;
}
}
}

// Check for column parity
if(colParity1 != RFbuffer_getBit() || colParity2 != RFbuffer_getBit() ||
colParity3 != RFbuffer_getBit() || colParity4 != RFbuffer_getBit() )
{
return FALSE;
}

// Check for stop bit
if(RFbuffer_getBit() != 0)
{
return FALSE;
}

// Prevents reading all zeros for customer ID and tag ID
for(count=0; count<5 && data[count] == 0; ++count);
if(count == 5)
{
return FALSE;
}

// Return TRUE if no errors in decoding received transponder data
return TRUE;
}

#endif