#include <stdio.h>
#include <reg5240.h>
// 0123456789012345678901234567890123456789012345678901234567890 123
char char7bit[64] = " !'#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_";
// 0123456789012345
char char5bit[16] = "0123456789:;<=>?";
// Initialize serial port 0 to 9600 baud using 22.1184 MHz crystal
void serialInit()
{
PCON |= 0x80;
SCON0 = 0x50;
TMOD |= 0x21;
TH1 = 0xDC;
CKCON |= 0x10;
TCON = 0x50;
SCON0 |= 0x02;
}
// Generate a long delay for card reset and read intervals.
void longDelay()
{
int i, j;
for (i = 1; i < 5; i++) {
for (j = 1; j < 5000; j++) {
;
}
}
}
// Generate a shorter delay (used between STROBE/DATA transitions)
void delay()
{
int i;
for (i = 1; i < 1000; i++) {
;
}
}
// Release the DATA line (P0.0) and allow it to float high.
void dataHigh()
{
P0 |= 0x01;
delay();
}
// Drive the DATA line (P0.0) low.
void dataLow()
{
P0 &= 0xFE;
delay();
}
// Release the STROBE line (P0.1) and allow it to float high.
void strobeHigh()
{
P0 |= 0x02;
delay();
}
// Drive the STROBE line (P0.1) low.
void strobeLow()
{
P0 &= 0xFD;
delay();
}
// Reset the card reader IC and cause it to clear its track A/B/C memory.
void resetCardReader()
{
dataHigh();
strobeHigh();
longDelay();
dataLow(); // Force DATA low
longDelay();
strobeLow(); // Drive STROBE low, then high again
strobeHigh();
strobeLow(); // Drive STROBE low, then release DATA
dataHigh();
longDelay();
strobeHigh(); // Drive STROBE low and high again two more times
strobeLow(); // to complete the reset and leave the card reader
strobeHigh(); // IC in the 'ready' state, prepared to scan a magstripe.
strobeLow();
}
// Wait for the DATA line to be driven low by the card reader.
void waitForDataLow()
{
int i = 0xFF;
dataHigh(); // Make sure that DATA is floating high
while ((i & 1) == 1) {
i = P0;
}
}
// Clock a single bit value out of the card reader by driving STROBE high,
// then low, and reading the DATA line.
int readBit()
{
int i;
strobeHigh(); // Drive STROBE high
strobeLow(); // Drive STROBE low (DATA line now contains bit)
i = P0;
if ((i & 1) == 0) {
return 1; // Low on DATA line indicates '1' bit
} else {
return 0; // High on DATA line indicates '0' bit
}
}
// Clock out and decode a 7-bit character from the track memory, returning the
// character value. 7-bit (alphanumeric) characters are found on track A only.
char read7BitChar()
{
int i, c;
// Each character is composed of 7 bits, which we clock out of the track memory
// beginning with the least significant bit. The 7th bit is parity, which is ignored.
c = 0;
for (i = 1; i < 128; i *= 2) {
c |= (readBit() * i);
}
c &= 0x3F;
return char7bit[c]; // Decode and return the character using the 7-bit table
}
// Clock out and decode a 5-bit character from the track memory, returning the
// character value. 5-bit (numeric+symbol) characters are found on tracks B and C.
char read5BitChar()
{
int i, c;
// Each character is composed of 5 bits, which we clock out of the track memory
// beginning with the least significant bit. The 5th bit is parity, which is ignored.
c = 0;
for (i = 1; i < 32; i *= 2) {
c |= (readBit() * i);
}
c &= 0x0F;
return char5bit[c]; // Decode and return the character using the 5-bit table
}
void main()
{
int i;
serialInit();
printf("DS5250 Magstripe Card Reader Demo\r\n");
P0 = 0xFF;
while (1)
{
resetCardReader();
printf("\r\n");
printf("Waiting for card swipe...\r\n");
printf("\r\n");
waitForDataLow(); // DATA low indicates card swipe has begun
strobeHigh();
longDelay();
strobeLow();
longDelay();
waitForDataLow(); // DATA low indicates card swipe has completed
// Discard preamble - 16 bit identifier code for card reader IC
for (i = 0; i < 16; i++) {
readBit();
}
// Track A - 76 characters, 7 bits per alphanumberic character including parity
printf("Track A > ");
for (i = 0; i < 76; i++) {
putchar(read7BitChar());
}
printf("\r\n\r\n");
// At this point, we've read 532 bits of the 704-bit Track A memory on the card reader IC.
// Flush the remaining 172 bits.
for (i = 0; i < 172; i++) {
readBit();
}
// Track B - 40 characters, 5 bits per numeric/symbol character including parity
printf("Track B > ");
for (i = 0; i < 40; i++) {
putchar(read5BitChar());
}
printf("\r\n\r\n");
/*
// In order to read Track C (which is rarely used on cards), we simply need to flush another
// (704-(40*5)) = 504 bits from the track memory as above, and then read another 107 characters
// from Track C as follows:
for (i = 0; i < 504; i++) {
readBit();
}
// Track C - 107 characters, 5 bits per numeric/symbol character including parity
printf("Track C > ");
for (i = 0; i < 107; i++) {
putchar(read5BitChar());
}
printf("\r\n\r\n");
*/
}
}
