Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

MagStripe Reader with Netduino


  • Please log in to reply
9 replies to this topic

#1 Thomas

Thomas

    Member

  • Members
  • PipPip
  • 15 posts
  • LocationDenmark

Posted 08 January 2011 - 04:50 PM

Hi,

I have been playing around with a Mag Stripe reader (the one I use only reads track 2), but at the moment it only works when I swipe the card very slowly through the reader.

The outputs from the reader is:

- Card Present
- Clock
- Data

When a card is swiped, the Card Present will first go low, and the clock wil start switching high and low, and when the clock goes from high to low, you are suppose to sample the data line, which becomes stable a short while before and keeps stable as long as the clock is low.

The clock is not constant, but depends on how fast you swipe the card. Swiping the card slowly results in something like 500 Hz, going about normal speed you will get a clock speed of roughly 1 to 1.5 kHz and swiping it fast will probably be 2-4 kHz.

I wrote some code (included below) which seemd to work when swiping the card slowly, but when the speeds get to what most people would do, it won't read the values correctly.

Am I using the InterruptPort correctly?

How long does the InputPort.Read() method take to read the pin state?

In the code below, I just put a breakpoint at the end of cp_OnInterrupt and look at the temp variable to see what was read.

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;

namespace MagStripeReader
{
    public class Program
    {
        public static byte[] data = new byte[1024];

        public static int count = 0;

        public static InputPort dataPin = new InputPort(Pins.GPIO_PIN_D6,
                                     false,
                                     Port.ResistorMode.PullUp);

        public static void Main()
        {
            // write your code here
            InterruptPort clk = new InterruptPort(Pins.GPIO_PIN_D10,
                                     false,
                                     Port.ResistorMode.PullUp,
                                     Port.InterruptMode.InterruptEdgeLow);
            clk.OnInterrupt += new NativeEventHandler(clk_OnInterrupt);


            InterruptPort cp = new InterruptPort(Pins.GPIO_PIN_D5,
                                     false,
                                     Port.ResistorMode.PullUp,
                                     Port.InterruptMode.InterruptEdgeHigh);
            cp.OnInterrupt += new NativeEventHandler(cp_OnInterrupt);

            Thread.Sleep(Timeout.Infinite); 
        }

        static void cp_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            bool inStartZone = true;
            bool inEndZone = false;

            byte[] temp = new byte[1024];
            int charCounter = 0;
            int bitCounter = 0;

            for (int i = 0; i < count; i++)
            {
                if (inStartZone && data[i] == 1)
                {

                }
                else if (inStartZone == false)
                {
                    bitCounter = 0;
                    if (data[i+0] == 0)
                    {
                        temp[charCounter] |= (byte)(1 << bitCounter);
                    }
                    bitCounter++;
                    if (data[i + 1] == 0)
                    {
                        temp[charCounter] |= (byte)(1 << bitCounter);
                    }
                    bitCounter++;
                    if (data[i + 2] == 0)
                    {
                        temp[charCounter] |= (byte)(1 << bitCounter);
                    }
                    bitCounter++;
                    if (data[i + 3] == 0)
                    {
                        temp[charCounter] |= (byte)(1 << bitCounter);
                    }
                    bitCounter++;

                    charCounter++;
                    i += 4;
                }
                else
                {
                    i--;
                    inStartZone = false;
                }
            }
            count = 0;
            return;
        }

        static void clk_OnInterrupt(uint data1, uint data2, DateTime time)
        {
            data[count] = 0;
            if (dataPin.Read())
            {
                data[count] = 1;
            }
            count++;
        }

    }
}


#2 bill.french

bill.french

    Advanced Member

  • Members
  • PipPipPip
  • 260 posts
  • LocationPrinceton, NJ

Posted 08 January 2011 - 06:28 PM

I was just reading about magstripe readers in a copy of Make magazine. I have no idea if this is relevant, but check this thread out, dealing with interrupt ports and IR: http://forums.netdui...p?showtopic=185

#3 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 08 January 2011 - 06:40 PM

Hi Thomas, InterruptPort samples are queued. They may take anywhere from a few microseconds to milliseconds to be raised in your code, depending on what else your code might be doing at the time. Each sample is timestamped. Here's what I'd recommend: 1. Create an array of incoming pulse switching from the data line. 2. In your clock line interrupt handler, compare the datetime of the clock line change to the datetimes of your data pulses (so you know what state the data line was at _when the clock line changed_). This should give you the sample you're looking for for data. Alternatively, you could create a set of arrays for both...and then parse the whole set of data when the card detect line showed "end of card data". Just be sure that you've captured all of the data points before you process them in this scenario. Chris

#4 Thomas

Thomas

    Member

  • Members
  • PipPip
  • 15 posts
  • LocationDenmark

Posted 08 January 2011 - 11:13 PM

Thanks for the suggestions, both of you! I'll try the caching of both clock and data with timestamps, and and see if I can get good captures that way. /Thomas

#5 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 08 January 2011 - 11:39 PM

I'll try the caching of both clock and data with timestamps, and and see if I can get good captures that way.

In addition to what Chris said, you can also use the second parameter of the interrupt handler (udata2), it contains the pin state at the time the interrupt has occurred, contrary to pin.Read() method call that retrieves the pin state while the interrupt handler routine is being executed.

#6 Thomas

Thomas

    Member

  • Members
  • PipPip
  • 15 posts
  • LocationDenmark

Posted 09 January 2011 - 12:12 AM

In addition to what Chris said, you can also use the second parameter of the interrupt handler (udata2), it contains the pin state at the time the interrupt has occurred, contrary to pin.Read() method call that retrieves the pin state while the interrupt handler routine is being executed.


Cool, thanks!

I guess that udata2 only holds the state of the pin triggering the interrupt, and not the other pins, but even then, this is what I need when constructing the two arrays.

/Thomas

#7 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 09 January 2011 - 09:24 AM

I guess that udata2 only holds the state of the pin triggering the interrupt, and not the other pins

Yes, that's right. If you want to get the state of other pins, you may check out sweetlilmre's post - he has built a custom firmware with extended InterruptPort, which passes an array of [watched] pin states to the interrupt handler.

#8 Thomas

Thomas

    Member

  • Members
  • PipPip
  • 15 posts
  • LocationDenmark

Posted 09 January 2011 - 12:07 PM

Yes, that's right. If you want to get the state of other pins, you may check out sweetlilmre's post - he has built a custom firmware with extended InterruptPort, which passes an array of [watched] pin states to the interrupt handler.


That looks very interesting!

Do you know if that firmware is available to test? I don't have access to the Keil Compiler so a binary FW would be what I needed.

Thanks,

/Thomas

#9 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 09 January 2011 - 12:35 PM

Do you know if that firmware is available to test? I don't have access to the Keil Compiler so a binary FW would be what I needed.

I think it has not been published anywhere on the forum, you'd need to ask sweetlilmre Posted Image

#10 Thomas

Thomas

    Member

  • Members
  • PipPip
  • 15 posts
  • LocationDenmark

Posted 12 January 2011 - 01:35 AM

Today I tried using interrupts for all the signals from the Mag Stripe reader, and saving the timestamps for later comparison, and that seems to work, even for really fast swiping. I'll try to wrap it all up in a nice library with error correction and all, and post it for all of you to try out and comment on. /Thomas




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.