?

Log in

Magnetic Stripe Card Reader with PIC12F683 - Goldtronics [entries|archive|friends|userinfo]
goldtronics

[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Magnetic Stripe Card Reader with PIC12F683 [Sep. 25th, 2008|03:38 pm]
goldtronics
[Tags|, , , , ]

Quick update: an I2C eeprom chip could be added for more memory, or a flash drive could be interfaced. USB flash drives, however, are difficult to interface because PICs do not have USB Host capabilities.

Project: Read a magnetic stripe (credit card or similar)

Background: I became interested in magstripes because my student card has one (two actually, one to get into my dorm and one to add money to, like debit), and I wanted to see what is on these stripes. There are many articles detailing how magstripes work and the data format:
http://www.msblabs.org/magstripe/
http://stripesnoop.sourceforge.net/devel/phrack37.txt

Theory: We are primarily concerned with the binary coming out of a card reader, and its format.

3 signals are generated:

/CP - Card Present (active low) - goes low when swiping a card
/DATA - Data (active low) - valid on low clock pulse
/STROBE - Clock (active low)

See diagram:


Format of the data:
Bytes are 5 bits wide, 4 data bits and one parity bit.
Bit 1, the least significant bit (LSB) is sent first.
There is a 16 character set - 10 data, 3 control, and 3 framing.

"The magstripe begins with a string of zeros to permit the self-clocking feature to "sync" with the data and begin decoding. A start sentinel [11010] then tells the reformatting process where to start grouping the decoded bitstream into groups of 5 bits each. At the end of the data, an "End Sentinel" is encountered, which is followed by an "Longitudinal Redundancy Check (LRC) character. The LRC is a parity check for the sums of all b1, b2, b3, and b4 data bits of all preceding characters. The LRC character will catch the remote error that could occur if an individual character had two compensating errors in its bit pattern (which would fool the 5th-bit parity check). "

Process: In order to obtain this information, we need a way to capture the bitstream and save it. A perfect task for a small microcontroller. I decided to use the PIC12F683 because it has an internal clock of 8MHz (plenty fast enough to capture the bitstream), can operate between 2 and 5V (battery powered from button cell or AAA), has many different types of interrupts (we'll use two in particular, external interrupt and IO change interrupt), enough IO pins (6, we'll use 3 for the card reader, and perhaps more for optional LED display), its small 8 pin footprint, and finally it has enough memory (96 bytes of user RAM and 256 bytes of EEPROM). We can read in a total of about 85 bytes (the typical credit card has about 38 bytes).

Program: Source code here (written in PIC assembly). First, we must initialize the microcontroller - this entails setting up the IO pins for digital input or output, enabling inuterrupts and edge trigger, and setting the internal oscillator. Also, if using display LEDs, to blink an LED to indicate "ready to scan."
Then we enter a loop where nothing happens, we simply wait until the card is read, that is, an interrupt occurs.
We connect the STROBE to the external interrupt pin of the PIC (GP2). The CARD PRESENT line is connected to GP3, which is set up for interrupt on change (that is, when the bit goes from low-to-high or high-to-low). DATA is connected to GP0 and is simply read by the microcontroller in the interrupt service routine (ISR).

The ISR is the bulk of this program. There are two entry points - the CP interrupt on change and the STROBE external interrupt, which will occur on the falling edge of the clock (high-to-low, though, theoretically, it shouldn't matter what edge we trigger on). Since there are two entry ways, the first thing the ISR checks is to see if the CP is high or low, if it is low we ignore it and start capturing the bitstream. The STROBE will be the source for most interrupts. Because the data is read on pin 0, we mask that bit by ANDing the rest of the port with 0, effectively clearing any other 1s that might be in it. We then ADD this bit into the first user register possible (we're going to need indirect addressing) and shift the register to the left to prepare for the next bit. After 5 bits are read in, we need to take complement of the byte because the data is read in complement form (low=1, high=0). Then we increment to the next byte and the next user register. That's the general principle, but there is a complication - making sure the 5 bits in each byte correspond to the same byte that's on the card, because the leading zeros can cause misalignment. This is easily fixed by saving the bitstream starting when the first 1 is read (from the start sentinel 11010).

Finally, the last interrupt will be CP going high, indicating we are done reading all the data in from the card. At this point we write all the data from the user registers into EEPROM and optionally blink an LED indicating we are done. We have saved our data in nonvolatile memory, so power can be turned off.

Shortcomings: There are a few shortcomings with this program, mostly with the user interface. The way I have written it, a card can be scanned once or twice, or a different card can be scanned second. The power must not be turned off in between scans, or the first scan data will be overwritten. I have not fully figured out the EEPROM write, I get spurious data the second time a card is read.

Error detection - I have not programmed any error detection. I do not make use of the parity bit, or the LRC at the end of the bitstream.

Also, once we have our data, we need to present it in a form understandable by the user, most easily done with a seven segment display and a momentary push button switch to view each character. This presents a problem. A switch requires another input pin, and a seven segment display requires seven output pins, however we only have three pins to work with. The seven segment display could be driven with two pins going to a shift register, and then to the seven segment display. We would need another chip, increasing the complexity and size. Or we could use another PIC with more IO pins.

Development: The next step will be to port the program to a PIC with more IO pins, in order to have a display. I'll also get a PIC with more EEPROM, so more cards can be read. The abilities of the user interface will be expanded, to include deleting a card from memory, rescanning a card, and a seven segment LED to display one character at a time.

I welcome ideas, comments, and questions.
LinkReply

Comments:
From: cohjj
2009-07-08 03:24 am (UTC)

So....

What was on the stripes?

(Reply) (Thread)
[User Picture]From: goldtronics
2009-07-08 11:12 am (UTC)

Re: So....

I read a credit card and found the same information that is on the front of the card, i.e. name, number, expiration.

I read my student card but I forget what was on it. Name and ID number, probably. The track that held our money on it was more dense (more bits per inch) and I couldn't figure out the data format.
(Reply) (Parent) (Thread)
[User Picture]From: pieceofbrain
2009-07-14 09:01 am (UTC)
The 3 free ports are enough to drive a display using 4094 register, as did I. :)
d-sheet
(Reply) (Thread)
[User Picture]From: goldtronics
2009-07-14 05:18 pm (UTC)
Not a bad idea. One could also connect two shift registers and drive a display and some flash memory. But why have three chips on a board when one could just choose a larger micro?
(Reply) (Parent) (Thread)
From: alpa4ino2
2009-08-21 01:31 am (UTC)

hy

hy,i sow ur articl about card reader,the source code and the way to store it..nice
i have just a question:do u use magnetic head +the pic prossesore+eeprom or magnetic head+2f2 decoder+pic+eeprom .
i mean do u directly connect the magnetic head to the pic ?and in witch pin u do that????
(Reply) (Thread)
[User Picture]From: goldtronics
2009-08-21 01:44 am (UTC)

Re: hy

The card reader has an F2F decoder on it. It outputs three signals to the PIC: /CardPresent, /Data, and /Strobe.

These signals are connected as stated in the code.

(Reply) (Parent) (Thread)
From: alpa4ino2
2009-08-21 02:54 am (UTC)

Re: hy

thanks bro,and be shure that am gona bather u with some other question.....
(Reply) (Parent) (Thread)
From: alpa4ino2
2009-08-24 11:31 pm (UTC)

Re: hy

well,thaks for ur reply,am gona ask u 2 question:
1.how u connect ur pic to ur pc to see what u wrote to ur eeprom
2.how to make my own pcb(like what is the best softwar to designe it and how to printed)....
thanks alot !
(Reply) (Parent) (Thread)
[User Picture]From: goldtronics
2009-08-25 01:51 am (UTC)

Re: hy

I connect the PIC to the PC via the programmer used to burn the firmware into the PIC. The programmer can also read the EEPROM out of the chip. I'm using the ICD2.

Most hobbiests use Eagle to capture schematics and layout circuit boards. I had PCBs made from BatchPCB and they did a great job. There are many tutorials about using Eagle online.
(Reply) (Parent) (Thread)
From: alpa4ino2
2009-08-25 02:34 am (UTC)

Re: hy

thanks
(Reply) (Parent) (Thread)
From: alpa4ino2
2009-08-28 12:40 am (UTC)

Re: hy

i have a frend that pout in a pcb the same pic chip an eeprom and the magtek controller,and throu a com cable he can retreave data from the pic from his pc,he didnt explaint to me how he didt......
my question is can we conecte the pic directli to the pc thru a com cable,and if yes witch pin of the pic will be ???
(Reply) (Parent) (Thread)
[User Picture]From: goldtronics
2009-08-28 07:19 pm (UTC)

Re: hy

No, the PIC runs off of 3 to 5 volts, but the serial port on your computer runs +9V and -9V so you need a level translator chip. Luckily, there's a very popular chip called the MAX232 that does all this for you.
(Reply) (Parent) (Thread)
From: alpa4ino2
2009-08-29 02:08 am (UTC)

Re: hy

thanks for ur advise
(Reply) (Parent) (Thread)