Magnetic Stripe Reader
Photograph
of the prototype hardware:
Circuit
diagram:
Controlling
program:
(*$d 2313 - uses an
AT90S2313*)
(*$c 4��� - 4MHz crystal in target*)
PROGRAM
MagneticStripeReader (input, output);
(* Scan a magnetic card
stripe for ISO 5-bit BCD format data (tracks 2,3),
�� convert to ASCII characters and send data to the serial port at
19200 baud*)
USES
� UART; (* library modules imported *)
CONST
� cardNotLoaded = 4;��� (*
port D lines used for input *)
� clockLine���� = 5;��� (* sample data on falling edge of clock *)
� dataLine����� = 6;��� (* data on this line is inverted: lo=1,
hi=0 *)
� BOD���������� = ';';� (* beginning of data sentinel *)
� EOD���������� = '?';� (* end of data sentinel *)
� CR����������� = #$0d; (*
carriage return *)
� LF����������� = #$0a; (*
line feed *)
TYPE
� TerrCode = (noError, overRun, frameErr); (* error codes returned
by UART RX *)
� TBdRate = (B2400, B4800, B9600, B19200);
VAR
� status : boolean;���� (* UART
TX status *)
� pinD�� : byte | sfr;� (* card reader attached to port D *)
� i����� : word;������� (* index used in GetChar: global for
speed *)
� ch���� : byte;������� (* char used in GetChar *)
� parity : boolean;���� (*
parity check *)
� ascCh� : char;������� (* ASCII char for sending via UART *)
� first� : boolean;���� (* flag for the first character read *)
(* Imported from UART *)
PROCEDURE
InitUART(bdRate:TBdRate); LIBRARY;
FUNCTION GotRXbyte(VAR
data:BYTE; VAR errCode:Terrcode):BOOLEAN; LIBRARY;
FUNCTION
PutTxbyte(data:BYTE):BOOLEAN; LIBRARY;
PROCEDURE
SendMessage(msg:string);
(* Send intro message to
UART *)
� VAR
��� i : word;
� BEGIN
��� FOR i:= 1 TO Ord(msg[0]) DO
����� WHILE NOT PutTxbyte(msg[i]) DO;(* wait for char to be sent *)
� END;
PROCEDURE SendCRLF;
(* Start a new line *)
��� REPEAT
��� UNTIL PutTxbyte(CR);
��� REPEAT
��� UNTIL PutTxbyte(LF);
� END;
FUNCTION GetChar(VAR
first: boolean):char;
(* get a character from
reader *)
� BEGIN
��� parity := FALSE;��������������
(* init. parity variable *)
��� ch:=#0;�����������������������
(* ready to build character *)
��� i:=1;�������������������������
(* index character bits *)
��� REPEAT
����� (* wait for clock to go low *)
����� WHILE Bit(pinD,clockLine)=#1 DO;
����� (* sample data line *)
����� IF Bit(pinD,dataLine)= #0 THEN (* data=1 [data inverted] *)
������� BEGIN
��������� ch:= ch + Chr(i);�������
(* add a '1' bit to code *)
��������� parity := NOT parity;���
(* toggle parity *)
��������� first := FALSE;���������
(* we now have the first '1' in data stream *)
������� END;
����� i:=i Shl 1;�����������������
(* index next bit position *)
����� IF first THEN i:=1;���������
(* reset index & wait for 1st '1' to arrive *)
����� (* wait for clock to go high again *)
����� WHILE Bit(pinD,clockLine)=#0 DO;
��� UNTIL i=%00100000;�� (*
all 5 bits collected? *)
���
��� ch:=(ch & #$0f)+#$30;��������� (* mask parity bit & convert to ASCII char *)
��� IF parity THEN (* good read (odd-parity) *)
����� GetChar := ch
��� ELSE
�� ���GetChar := '*'; (*
return a dummy char for bad read *)
� END;
BEGIN
� InitUART(B19200);���� (*
initialize UART *)
� SendMessage("Magnetic Stripe");
� SendMessage(" Reader V1.1"); SendCRLF;
� Wait(500); (* wait 0.5s for reader to power-up *)
� REPEAT
��� (* wait for card to be
loaded *)
��� WHILE Bit(pinD,cardNotLoaded)=#1 DO;
��� (* get and display other data *)
��� first := TRUE;� (* flag
first char to be read *)
��� REPEAT
����� ascCh := GetChar(first);������ (* get 1 character from reader *)
���� �status :=
PutTXbyte(ascCh);��� (* send to UART *)
��� UNTIL (ascCh = EOD)OR(Bit(pinD,cardNotLoaded)=#1);
��� SendCRLF;
��� (* wait for card to be unloaded *)
��� WHILE Bit(pinD,cardNotLoaded)=#0 DO;
� FOREVER;
END.