Jump to content
43oh

RDM630 Wiegand RFID Reader Decoding


Recommended Posts

Here's some code I ported over from the Arduino to work on the MSP430G series.

 

It's for decoding the Wiegand protocal used in this RFID reader:

http://www.seeedstudio.com/depot/125khz ... th=144_153

 

It will print any detected RFID cards 3 byte ID over serial in HEX. Ports 1.4/1.5 are used for DATA0/DATA1

 

//  Copyright (c) 2010 seeed technology inc.
//  Author: Icing Chang
//  Version: september 2, 2010
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//
//  Modified to by touch to work on the MSP430.

#include 
#define UART_TXD   0x02             // TXD on P1.1 (Timer0_A.OUT0)
#define UART_TBIT_DIV_2 (1000000 / (9600 * 2))
#define UART_TBIT (1000000 / 9600)

char RFIDcardNum[3];
char evenBit = 0;
char oddBit = 0;
char isData0Low = 0;
char isData1Low = 0;
int recvBitCount = 0;
char isCardReadOver = 0;

int checkParity();
void resetData();

void TimerA_UART_init(void);
void TimerA_UART_tx(unsigned char byte);
void TimerA_UART_print(char *string);
unsigned int txData;   // UART internal variable for TX

void main(void)
{
WDTCTL = WDTPW + WDTHOLD;	// Stop watchdog timer
BCSCTL1 = CALBC1_1MHZ;
DCOCTL = CALDCO_1MHZ;

P1SEL = UART_TXD; 
P1DIR = UART_TXD + BIT0;            

P1IES |= 0x01;
P1IFG = 0;
P1IE |= BIT4 + BIT5; 

_BIS_SR(GIE); 
TimerA_UART_init();
TimerA_UART_print("RFID Ready:");
while(1){
	if(isData0Low||isData1Low){
	    if(1 == recvBitCount){//even bit
	      evenBit = (1-isData0Low)&isData1Low;
	    }
	    else if( recvBitCount >= 26){
	      oddBit = (1-isData0Low)&isData1Low;
	      isCardReadOver = 1;
	    }
	    else{
	      //only if isData1Low = 1, card bit could be 1
	      RFIDcardNum[2-(recvBitCount-2)/8] |= (isData1Low << (7-(recvBitCount-2)%8));
	    }
	    //reset data0 and data1
	    isData0Low = 0;
	    isData1Low = 0;
	  }
	  //print the card id number
	  if(isCardReadOver){
		    if(checkParity()){
		    	TimerA_UART_print(RFIDcardNum);
		    	__delay_cycles(100000);
		    }
	    resetData();
	  }
}
}

int checkParity(){
 int i = 0;
 int evenCount = 0;
 int oddCount = 0;
 for(i = 0; i < 8; i++){
   if(RFIDcardNum[2]&(0x80>>i)){
     evenCount++;
   }
 }
 for(i = 0; i < 4; i++){
   if(RFIDcardNum[1]&(0x80>>i)){
     evenCount++;
   }
 }
 for(i = 4; i < 8; i++){
   if(RFIDcardNum[1]&(0x80>>i)){
     oddCount++;
   }
 }
 for(i = 0; i < 8; i++){
   if(RFIDcardNum[0]&(0x80>>i)){
     oddCount++;
   }
 }

 if(evenCount%2 == evenBit && oddCount%2 != oddBit){
   return 1;
 }
 else{
   return 0;
 }
}

void resetData(){
 RFIDcardNum[0] = 0;
 RFIDcardNum[1] = 0;
 RFIDcardNum[2] = 0;
 evenBit = 0;
 oddBit = 0;
 recvBitCount = 0;
 isData0Low = 0;
 isData1Low = 0;
 isCardReadOver = 0;
}

#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
if(P1IFG & BIT4){
	recvBitCount++;
	isData1Low = 1;
}
if(P1IFG & BIT5){
	recvBitCount++;
	isData0Low = 1;
}
P1IFG = 0;
}

//------------------------------------------------------------------------------
// Function configures Timer_A for full-duplex UART operation
//------------------------------------------------------------------------------
void TimerA_UART_init(void)
{
   TACCTL0 = OUT;                          // Set TXD Idle as Mark = '1'
   TACCTL1 = SCS + CM1 + CAP + CCIE;       // Sync, Neg Edge, Capture, Int
  	TACTL = TASSEL_2 + MC_2;                // SMCLK, start in continuous mode
}

//------------------------------------------------------------------------------
// Outputs one byte using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_tx(unsigned char byte)
{
   while (TACCTL0 & CCIE);                 // Ensure last char got TX'd
   TACCR0 = TAR;                           // Current state of TA counter
   TACCR0 += UART_TBIT;                    // One bit time till first bit
   TACCTL0 = OUTMOD0 + CCIE;               // Set TXD on EQU0, Int
   txData = byte;                          // Load global variable
   txData |= 0x100;                        // Add mark stop bit to TXData
   txData <<= 1;                           // Add space start bit
}

//------------------------------------------------------------------------------
// Prints a string over using the Timer_A UART
//------------------------------------------------------------------------------
void TimerA_UART_print(char *string)
{
   while (*string) {
       TimerA_UART_tx(*string++);
   }
}

//------------------------------------------------------------------------------
// Timer_A UART - Transmit Interrupt Handler
//------------------------------------------------------------------------------
#pragma vector = TIMERA0_VECTOR
__interrupt void Timer_A0_ISR(void)
{
   static unsigned char txBitCnt = 10;

   TACCR0 += UART_TBIT;                    // Add Offset to CCRx
   if (txBitCnt == 0) {                    // All bits TXed?
       TACCTL0 &= ~CCIE;                   // All bits TXed, disable interrupt
       txBitCnt = 10;                      // Re-load bit counter
   }
   else {
       if (txData & 0x01) {
         TACCTL0 &= ~OUTMOD2;              // TX Mark '1'
       }
       else {
         TACCTL0 |= OUTMOD2;               // TX Space '0'
       }
       txData >>= 1;
       txBitCnt--;
   }
}     

Link to post
Share on other sites
O_O good stuff touch. Thanks for sharing. Maybe we should have a small contest pool for the code vault and ported over code.

 

that would be neat. You could require that the code is formatted in a library or some thing so it would be easy to use.

Link to post
Share on other sites

I think this is a good idea too.

 

We might have to come up with function templates for how code is called ie: a standard and expected way of doing things.

 

But I have to ask, isn't MSPhere doing this already with his library work?

Link to post
Share on other sites

I bought a few of these Parallax units when Radio Shack (You've got questions, we've got blank stares) had them on clearance for $10. :D

 

They're serial, so not the same as touch's, but I really should figure out how to read them with the MSP430. ;) How many bytes can you store in flash on the 16-pin value line chips? The ids are 10 bytes each.

Link to post
Share on other sites
I bought a few of these Parallax units when Radio Shack (You've got questions, we've got blank stares) had them on clearance for $10. :D

 

They're serial, so not the same as touch's, but I really should figure out how to read them with the MSP430. ;) How many bytes can you store in flash on the 16-pin value line chips? The ids are 10 bytes each.

 

Hey Geek, yeah, when I go to "The Shack," I usually just say "I'm going to the parts drawers" and they leave me alone, aside from some cell phone/battery sales talk. I used to respect Radio Shack employees, but not any more. About the Parallax RFID reader, I picked up a few myself, and I have code for the MSP430 for them. It's just that my code is always so ugly I rarely share it, but if you just want something to start from, let me know, and I'll post/pm you it. I wish I wrote cleaner code... I have so much just sitting on my HDD!

Link to post
Share on other sites

I wanted to get some of the Parallax RFID readers but my Radio Shack had none :( .

 

Looking at the specs they appear to use a 10byte card ID, the RDM630 cards appear to be 3 byte only.

 

I also wondered about storing stuff in flash, as I wasn't able to find anything on storing stuff in the MSP430's flash memory. I had originally planned on making it so I could authorize or de-authorize cards from my RFID reader, but just ended up hardcoding the card ID's.

Link to post
Share on other sites

There is a monitor(pdf) program for the MSP430. You can store your IDs via the UART or probably even look through the code on how they use the flash.

 

Also the "Flashing DCO constants" thread has some code on writing into Flash memory(Seg A)

viewtopic.php?f=10&t=239&hilit=flash#p1803

Flash_ptrA = (char *)0x10C0;              // Point to beginning of seg A
 FCTL2 = FWKEY + FSSEL0 + FN1;             // MCLK/3 for Flash Timing Generator
 FCTL1 = FWKEY + ERASE;                    // Set Erase bit
 FCTL3 = FWKEY + LOCKA;                    // Clear LOCK & LOCKA bits
 *Flash_ptrA = 0x00;                       // Dummy write to erase Flash seg A
 FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation
 Flash_ptrA = (char *)0x10F8;              // Point to beginning of cal consts
 for (j = 0; j     *Flash_ptrA++ = CAL_DATA[j];            // re-flash DCO calibration data
 FCTL1 = FWKEY;                            // Clear WRT bit
 FCTL3 = FWKEY + LOCKA + LOCK;             // Set LOCK & LOCKA bit

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...