Magnetic strip card reader project

#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");

*/

}
}