home *** CD-ROM | disk | FTP | other *** search
-
- Magnetic stripe technology
-
-
- Figures and listings are at the end.
-
- Because of their widespread use, most magnetic cards adhere to well-defined
- standards that describe the physical and magnetic characteristics for a
- magnetic stripe on a plastic card. These standards outline specifications for a
- storage format and information interchange. This does not preclude other
- encoding techniques or additional data tracks for specific applications, but in
- most cases it makes sense to adhere to at least the basic constraints. This
- gives you the choice of using any commercially available magnetic encoders for
- your application. The technique used for encoding magnetic cards is known as
- "Two-Frequency, Coherent Phase Recording". Allowing for the representation of
- single-channel, self-clocking serial data, this methodology is generally
- referred to as F/2F. Self-clocking is achieved by combining data and clock bits
- together in a continuous, synchronous sequence. In this scheme, an intermediate
- flux transition signifies a one bit and the absence of an intermediate flux
- transition denotes a zero bit.
- Three data tracks defined for use on standard magnetic cards each possess
- different bit densities and encoded character sets. The average bit density of
- track 1 is 210 bits per inch (bpi). Track 1 characters are made up of six data
- bits and an odd parity bit, encoded with the least-significant bit first and
- the parity bit last, yielding a 64-character set. Taking the number of bits per
- inch and the number of bits per character, you can see track 1 has the capacity
- to hold 79 characters.
- Track 2 has a bit density of 75 bpi, and track 3 uses 210 bpi. Both of these
- tracks allow the representation of a numeric-only character set. The characters
- for tracks 2 and 3 are encoded using a 4-bit binary-coded decimal subset with
- odd parity and, like track 1, are encoded with the least significant bit first
- and the parity bit last. The lower density of track 2 allows up to 40 numeric
- characters, where 107 numerics can be squeezed onto track 3. The actual number
- of usable characters will be fewer since you also have the Start Sentinel, End
- Sentinel, and LRC characters.
- Though sometimes magnetic cards are moved past the read head mechanically,
- most applications rely on manually moving the card, either through a slotted
- reader or into an insertion-type reader. Typically the swipe rate is 5-20 inches
- per second (ips), with 50 ips being the fastest most card readers can handle. Of
- course, moving the card by hand will not only result in varying the absolute
- card velocity but, will also introduce incremental speed changes as the card
- accelerates and decelerates past the pickup. The F/2F scheme is very forgiving
- of such speed fluctuations.
- For all 3 tracks, the fundamental data format is similar and consists of the
- following elements: First, leading zero bits are encoded to indicate the
- presence of an encoded magnetic card and provide synchronization pulses to the
- read head electronics and ultimately to the controller. Next, the Start Sentinel
- character is encoded which indicates the start of the actual data. The coded
- data follows. Next, the End Sentinel terminates the data portion of the card
- and followed by an LRC byte (used for error detection). The LRC is essentially
- a horizontal parity calculated by an exclusive-OR of all the data bits from the
- Start Sentinel to the End Sentinel (inclusive). Finally, trailing zeros follow
- the LRC and fill out the remainder of the card.
- ANATOMY OF A MAGNETIC CARD
- The magnetic tracks have inherent characteristics based on details such as
- code set and bit and character densities. International organizations such as
- Mastercard and VISA impose additional constraits for their participating members
- and standards exist for bank debit cards and ATM cards as well. These rules
- specify the exact content and format of each data field in aech track as well as
- the intended uses for the tracks. Naturally, for nonfinancial uses, it is not
- necessary to comply with these standards. For dedicated uses such as access
- control, people tracking, and material tracking, adhering to the minimal
- standards is adequate.
- The most-often-used track is track 2, although it offers the lowest inform-
- ation density of the three. It contains all the information that is normally
- used for credit card transactions. When a customer name is required, track 1
- must be used since it is the only track that permits alphanumeric data. Track 3
- is specified for numeric-only data, but is unique. It is intended for change-
- able data and consequently may not only be read but may be rewritten by the
- transaction-handling equipment. A multitude of data fileds are contained in
- these various tracks. Figure 1 shows a brief run-down of what is generally
- placed on tracks 1 and 2.
- REAL CARD READERS
- The recovery of magnetically encoded F/2F data can be accomplished directly
- with the use of just about any microcontroller. There are no particular
- difficulties in deciphering the raw F/2F data stream and many early magnetic
- read heads contained nothing more than signal amplifiers and line drivers.
- These are now artifacts since all modern magnetic read heads contain integ-
- rated F/2F bit recovery circuitry and interface with the host controller in a
- standard fashion using three wires: CARD PRESENT, CLOCK, and DATA. The read
- heads usually rely on a single chip to perform the linear signal conditioning,
- sychronization, and recovery of individual bits from the data stream. The Mag-
- Tek 21006505 IC is representative of this type of data recovery circuit and its
- functionality is depicted in figure 2.
- Linear conditioning consists of raising the level of the magnetic pickup's
- input signal, rejeting common-mode noise, conditioning and detecting the
- signal, and finally providing a digital output for susequent processing. The
- enable/disable counters provide initialization for the recovery section. The
- recovery section locks onto the data rate and recovers the individual data bits
- from the data stream. The oscillator section provides the clocks for the recov-
- ery section and for the enable/disable timers. Card present goes low after 8 or
- 9 flux reversals are seen from the magnetic pickup and will return high about
- 50 ms after the last flux reversal. The strobe line signals that data is valid
- and is active low. The data pin indicates a one bit when it is low. Raw F/2F
- data can also be picked directly off the chip.
- The data rate for a high-density trac scanned at 50 ips comes to 10500 bits
- per second (bps). This results in a transfer rate of 1500 characters per second
- for the 7-bit elements used on track 1, and 2100 characters per second using
- the 5-bit elements of track 3. I either case, this translates to a new bit
- arriving at the controller just under every 100 us (microsecond). Even the most
- anemic controller should be able to keep up. With resonably good coding techni-
- ques, there should be no problem handling the entire data sampling phase on an
- interrupt-driven basis. The low-density (track 2) data flows at a more pedes-
- trian 3750 bps, yielding 750 5-bit characters per second, or a new bit every
- 266 us. Since most dual-track read heads provide track 1 and track 2 data, this
- indicates that handling both tracks simultaneously is feasible under interrupt
- control. Keep in mind that 50 ips is a rather fast scan rate; 20-30 ips is
- probably a more realistic limit.
- MAGNETIC BIT STORMS
- When approaching a problem such as decoding magnetic cards, it pays to spend
- some time looking at the overall picture before starting to write the code. At
- first glance, it would seem that organizing the data into the prevailing element
- size during the sampling interval would make decoding easier. This could be
- easily done by ignoring all the leading zeros, with actual data storage comm-
- encing with the first one bit. Of course, this approach assumes you're getting
- good data. The fact that the data recovery is handled using well-proven hard-
- wae makes this assumption valid.
- If all you need to do is decode the card in a forward direction, then going
- about things as I just described makes sense and reduces the coding effort to a
- trivial exercise. If you have to support reverse decoding then this is not the
- optimal solution. Having considered the tradeoffs of being able to decode a
- magnetic card in both forward and reverse directions, I decided to structure the
- program to work equally well in either direction at the cost of a slight
- increase in initial complexity.
- The first step in decoding is to acquire the serial bit stream. This can be
- done using a dedicated sample loop or, with a little more work, using interrupt
- processing. Since the idea is the same regardless of the details, I decided to
- use a sample loop in my demonstration program (isting 1). The code simply
- records the incoming data stream and deposits the data in a sample buffer a byte
- at a time. Sampling begins when Card Present returns idle. Any incomplete byte
- that has been partially assembled at the time when sampling terminates is simply
- discarded. The abundance of leading and trailing zeros allows losing some bits
- at either end causing any problems.
- Once the sampling interval completes, control is transferred to the decoding
- algorithm. Presented in listing 2, the track-1 decode algorithm consists of
- nothing more than some initialization and the essence of the decode logic.
- Limiting the gyrations contained in the main body of this routine not only makes
- the logic easy to follow, but permits the same code to handle the decoding in
- either a forward or reverse direction.
- The initial entry point assumes a forward decode attempt and sets up the
- necessary flags, pointers, and counters before jumping into the main initial-
- ization code. After initialization, the sample buffer is scanned for the first
- one bit, at which time a 7-bit element is assembled. If the parity is correct
- and the character code checks out to be a Start Sentinel, the code proceeds and
- starts pulling successive data elements from the sample buffer. If the data
- element is not an End Sentinel, the character is translated to ASCII and stored
- in the decode buffer. Should an End Sentinel be detected, the program extracts
- the next character, which is assumed to be the LRC byte, and finally checks the
- calculated LRC for a value of zero.
- The checks and balances included in the execution of this loop include things
- such as parity, a cumulative LRC, and checking to make sure I haven't run out of
- samples. If everything checks out, the program terminates and returns with the
- DPTR pointing to the decoded data buffer and the character count contained in
- ACC. Should a decode failure occur, a test is performed on the direction flag
- and if this is an attempt at a forward decode, the routine jumps to the reverse
- initialization entry point. The reverse entry is similar to the forward decode
- entry but sets up the sample pointer to the end of the sample buffer and sets
- the direction flag to indicate a reverse operation.
- The routines contained in the intermediate layer are shown in listing 3. The
- meaning and operation of these routines should be apparent. The key routine in
- this section is GET_BIT, which picks off the next bit from the sample buffer,
- essentially restoring the sequential nature of the initial magnetic bit stream.
- FIND_START is used to synchronize with the first one bit. GET_CHAR first checks
- to make sure it hasn't run out of samples, then assembles the next 7-bit data
- element while doing a parity test and LRC calculation. Any problems encountered
- here are sent back to the caller and are handled there. STORE_CHAR translates
- and deposits the data character into its respective location in the decoded-data
- buffer and increments the character counter.
- Listing 4 shows the low-level code. These routines perform the most rudiment-
- ary functions and operate in accordance with the direction flag. INDEX_PTR
- either increments or decrements the sample pointer, POSITION_BIT likewise does
- either a right or left shift and LOCATE_BIT returns the state of the least- or
- most- significant bit of the accumulator.
- GO AHEAD, TAKE A SWIPE
- Let me touch on a few additional points that may not be immediately apparent
- before signing off. Storing the sampled data in a continuous stream makes the
- sample routine work equally well with the various bit configurations used for
- the different recording tracks. This would not be easily attained if you tried
- to generate a particular element format during sample time. Furthermore, if you
- look at the differences between the encoded character sets and the bit formats
- for the different tracks, you will find that they differ in only a few areas.
- With a few minor changes, such as the defined Start Sentinel, number of bits per
- element, and character translation method, the decode routine I've shown could
- easily be coerced to handle the decoding of any of the standard magnetic tracks.
- As a matter of fact, by recoding and redefining the hard-coded constants as
- variables, these could be set up for the particular data track at execution
- time before invoking the decode function. Doing so would not only save program
- memory, but would also allow you to use a routine you were comfrtable with.
-
- *******************************************************************************
- FIGURE 1
- _____________________________________________________________________
- TRACK 1 |SS|FC| PAN |FS| NAME |FS| ADDITIONAL DATA |ES|LRC|
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Notes: Track 1 is limied to 79 characters including SS, ES, and LRC.
- Mastercard PAN is variable up to 16 characters maximum. VISA is 13 or 16
- characters, including mod-10 check digit.
- SS: Start sentinel (%)
- FC: Format code
- FS: Field separator ({)
- ES: End sentinel (?)
- LRC: Longitudinal redundency check character
- PAN (primary account number): 19 digits max.
- NAME: 26 alphanumeric characters max.
- ADDITIONAL DATA: Expiration date 4
- Restriction or type 3
- Offset or PVN 5
- ______________________________________________________________________
- TRACK 2 |SS|FC| PAN |FS| ADDITIONAL DATA |ES|LRC|
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- SS: Start sentinel (;) (hex B)
- FS: Field separator (=) (hex D)
- ES: End sentinel (?) (hex F)
- LRC: Longitudinal redundency check character
- PAN (primary account number): 19 digits max.
- ADDITIONAL DATA: Expiration date 4
- Restriction or type 3
- Offset or PVN 5
-
- *****************************************************************************
- FIGURE 2
- HEAD SIGNAL __/~\__ __/~\__ __/~\__ __/~\__ __/~\__ __/~\_______
- `-` `-` `-` `-` `-`
- ____ _______ __________ ____
- CARD PRESENT |______________________________________________|
-
- ____ ____ _____________________ ____ ____ _____
- READ DATA |____| |_________| |_________|
-
- ____ ______ __________ __ __ __ __ __ __ __ __ __ __
- READ STROBE |__| |_| |_| |_| |_| |_| |_| |_| |_| |_| |
-
- | 0| 1| 0| 1| 1| 0| 1| 1| 0| 0|
-
-
- ___
- HEAD 1-----X---X--------13 |MAG| 9--C2-R3
- R1 C1 |TEK| |
- HEAD 2-----X---X--------12 | | 10-----X--X
- | | | |
- X---X------11 | | | R5
- X-X R2 C6 | | 6------|--X
- | | X---X-------8 | | |
- +5VDC --------------X--R7--X--------X-|-----------------14 | | 7-----C3
- | |+ | | | ____
- R6 C5 | | | 16----DATA
- | X----------|------------------5 | | ______
- ____ _______ | | X------------------2 | | 15----STROBE
- CARD PRESENT -------X------|-----------------------------1 | |
- | X----X-----3 | |
- | C4 R4----4 | |
- GND------------------------X------------------X |___|
-
- R=RESISTOR(Values weren't given)
- C=CAPACITOR(Values weren't given)
- X=CONNECTION BETWEEN WIRES
- MAG TEK is the Mag-Tek 21006505
-
- *****************************************************************************
- LISTING 1-- Using several externally defined routines, a sample program to
- read a stripe and store it in a buffer is very short.
-
- PUBLIC READ_MAG1
- EXTERN MS1_BUF (XDATA) ;sample buffer
- EXTERN MS1_LIM (NUMBER) ;sample limit
- EXTERN MD1_BUF (XDATA) ;decode buffer
- EXTERN CP (BIT) ;card present bit
- EXTERN M1_CLK (BIT) ;clock bit
- EXTERN M1_DQ (BIT) ;data bit
-
- M1_SS EQU 5 ;start sentinel
- M1_ES EQU 1FH ;end sentinel
- ;
- SEG CODE
- ;Sampe and decode magnetic track 1
- ; output: ACC contains character count.
- ; DPTR points to data buffer
- READ_MAG1 PROC
- CALL MAG_SAMPLE
- JZ L?RM1
- CALL MAG1_DECODE
- L?RM1: RET
- ENDPROC
- ;General-purpose magnetic sampling routine
- ; output: ACC contains sample count
- MAG_SAMPLE PROC
- MOV DPTR,#MS1_BUF
- MOV R1,#0 ;sample counter
- L?MS1: MOV R0,#8 ;bit counter
- L?MS2: JB CP,L?MS4
- JB M1_CLK,L?MS2
- MOV C,M1_DQ
- L?MS3: JB CP,L?MS4
- JNB M1_CLK,L?MS3
- CPL C
- RRC A
- DJNZ R0,L?MS2
- MOVX @DPTR,A
- INC DPTR
- INC R1 ;sample counter
- CJNE R1,#MS1_LIM,L?MS1
- L?MS4: MOV A,R1 ;final sample count
- RET
- ENDPROC
-
- *******************************************************************************
- LISTING 2-- Once the serial bit stream has been acquired, the decoding
- algorithm takes over.
-
- ;Bidirectional magnetic track 1 decode routine
- ;input: sample count in ACC, output: ACC contains character count
- ; DPTR points to decoded data buffer
- ;Reg. usage for this routine (includes subroutines) as follows:
- ;R5: Direction flag, 0=forward
- ;R4: Cumulative LRC register
- ;R3: Decoded character counter
- ;R2: Nondecrementing sample count
- ;R1: Decrementing sample count
- ;R0: Bit syncronizing counter
- MAG1_DECODE PROC
- ;1st pass, setup for forward decode attempt
- MOV R5,#0 ;indicate forward decode
- MOV DPTR,#MS1_BUF ;point to start of buffer
- MOV R1,A ;sample counter
- MOV R2,A ;sample count
- JMP L?M1D1
- L?M1D0: ;2nd pass, setup for reverse decode attempt
- MOV R5,#1 ;indicate reverse decode
- MOV DPTR,#MS1_BUF
- MOV A,R2 ;sample count
- DEC A
- ADD A,DPL
- MOV DPL,A
- CLR A
- ADDC A,DPH
- MOV DPH,A ;point to end of buffer
- MOV R1,2 ;sample counter
- L?M1D1: ;decode initialization
- MOV R3,#0 ;character counter
- MOV R4,#0 ;inital LRC
- MOV R0,#0 ;bit syncronizer
- CALL FIND_START ;main decode loop
- JNC L?M1D5 ;start bit error
- CALL GET_CHAR ;Start Sentinel
- JB ACC.7,L?M1D5 ;format error
- CJNE A,#M1_SS,L?M1D5 ;start setinel error
- L?M1D2: ;daa byte or End Sentinel
- CALL GET_CHAR
- JB ACC.7,L?M1D5 ;format error
- CJNE A,#M1_ES,L?M1D3 ;end sentinel not found
- JMP L?M1D4
- L?M1D3:
- CALL STORE_CHAR ;data character
- JMP L?M1D2
- L?M1D4: ;LRC
- CALL GET_CHAR ;get LRC
- JB ACC.7,L?M1D5 ;format error
- MOV A,R4
- JNZ L?M1D5 ;LRC error
- MOV DPTR,#MD1_BUF ;good return
- MOV A,R3 ;final character
- RET
- L?M1D5: ;decode error, check if 1st pass
- CJNE R5,#1,L?M1D0 ;check direction
- CLR A ;bad return
- RET
- ENDPROC
-
- *******************************************************************************
- LISTING 3-- The intermediate layer of software is one level removed from the
- nitty-gritty details.
-
- ;Get the next bit from the sample buffer
- ;output: C contains data bit
- GET_BIT PROC
- CJNE R0,#0,L?GB1 ;bit synchronizer
- MOV R0,#8
- PUSH ACC
- MOVX A,@DPTR
- CALL INDEX_PTR
- MOV B,A
- POP ACC
- DEC R1 ;sample counter
- L?GB1: XCH A,B
- CALL POSITION_BIT
- XCH A,B
- DEC R0 ;bit synchronizer
- RET
- ENDPROC
- ;
- ;Find the first '1' bit in the sample buffer
- ;output: C=1 if bit is found
- FIND_START PROC
- L?FS1:
- CJNE R0,#0,L?FS2 ;bit synchronizer
- MOV R0,#8
- MOVX A,@DPTR
- CALL INDEX_PTR
- DJNZ R1,L?FS2 ;sample counter
- JMP L?FS4 ;out of samples
- L?FS2: CALL LOCATE_BIT ;test for a '1' bit
- JC L?FS3
- CALL POSITION_BIT
- DEC R0 ;bit synchronizer
- JMP L?FS1
- L?FS3: ;good return
- MOV B,A ;save copy in B
- SETB C
- RET
- L?FS4: CLR C ;bad return
- RET
- ENDPROC
- ;
- ;Get the next 7 bit element from the sample buffer
- ;output: ACC contains data element
- ; error flag is ACC.7
- GET_CHAR PROC
- MOV A,R1 ;sample counter
- JZ L?GC2 ;out of samples
- MOV R7,#7 ;bit counter
- CLR A
- L?GC1: CALL GET_BIT ;next bit
- RRC A
- DJNZ R7,L?GC1
- RR A
- JNB P,L?GC2 ;parity error
- ANL A,#3FH ;discard parity
- PUSH ACC
- XRL A,R4 ;calculate LRC
- MOV R4,A
- POP ACC ;good return
- RET
- L?GC2: SETB ACC.7 ;bad return
- RET
- ENDPROC
- ;Translate and store the data character
- ;input: ACC contains data character
- STORE_CHAR PROC
- PUSH DPL
- PUSH DPH
- PUS ACC
- MOV DPTR,#MD1_BUF
- MOV A,R3 ;character counter
- ADD A,DPL
- MOV DPL,A
- CLR A
- ADDC A,DPH ;generate displacement
- MOV DPH,A
- POP ACC
- ADD A,#' ' ;translate
- MOVX @DPTR,A ;store
- POP DPH
- POP DPL
- INC R3 ;character counter
- RET
- ENDPROC
-
- *******************************************************************************
- LISTING 4-- The low-level routines get right down to the ground and take care
- of the gory details.
-
- ;Index the sample pointer either forward or backward
- INDEX_PTR PROC
- CJNE R5,#0,L?IP1 ;check direction
- INC DPTR ;forward
- RET
- L?IP1: PUSH ACC ;backward
- DEC DPL
- MOV A,DPL
- CJNE A,#-1,L?IP2
- DEC DPH
- L?IP2: POP ACC
- RET
- ENDPROC
-
- ;Position bit is in ACC into C in either a right or left shift
- POSITION_BIT PROC
- CJNE R5,#0,L?PB1 ;check direction
- RRC A ;forward
- RET
- L?PB1: RLC A
- RET
- ENDPROC
-
- ;Locate a 1 bit, either msb or lsb
- ;output: C=1 if bit is a one
- LOCATE_BIT PROC
- CJNE R5,#0,L?LB1 ;check direction
- MOV C,ACC.0 ;forward
- RET
- L?LB1: MOV C,ACC.7 ;backward
- RET
- ENDPROC
-
- *******************************************************************************
- Contact:
- Mag-Tek, Inc.
- 20725 S. Annalee Ave.
- Carson, CA 90746
- (213) 631-8602
- fax: (213) 631-3956
- *******************************************************************************
-