Code Download

The code and documentation is available on GitHub by clicking the green button below. Select Download Zip to get the code and documentation.

Code Review

The first part is the data reading loop, which grabs the first ~80 non-zero bytes. We have to toss out the zeros as they are just buffers on the edge of the magstripe. There should be at least 4 but we don't use them so they get ignored in the loop.

// for lots more info, see 
// http://stripesnoop.sourceforge.net/devel/magtek-app.pdf

void loop()
{
  // wait till the card ready pin is low
  while (digitalRead(CARD2));
  
  uint8_t zeros = 0;
  uint8_t parityok = 0;
  
  // card was swiped!
  // check clocked in data
  for (uint8_t t1 = 0; t1 < TRACK1_LEN; t1++) {
    track1[t1] = 0;
    for (uint8_t b=0; b < BYTELENGTH; b++) {

      // wait while clock is high
      while (digitalRead(CLOCK2) && !digitalRead(CARD2));
      // we sample on the falling edge!
      uint8_t x = digitalRead(DATA2);
      if (!x) {
      // data is LSB and inverted!
        track1[t1] |= _BV(b);
      }
      // heep hanging out while its low
      while (!digitalRead(CLOCK2) && !digitalRead(CARD2));
     
    }
    
    if ((t1 == 0) && (track1[t1] == 0)) {
     // get rid of leading 0's
     zeros++;
     t1--;
     continue;
    }
    
    // we must have some leading zeros!
    if (zeros < 4) {
      t1--;
     continue;
    }
    
    // if the second byte is a zero, theres noise, backtrack
    if ((t1 == 1) && (track1[t1] == 0)) {
     t1 = -1;
     zeros = 1;
     continue;
    }
  }
  
  // all the data is read into the track1 buffer
  
  // shift left until we have no more starting zero bits!
  while ((track1[0] & 0x1) == 0 ) {
    shifttrack(track1, scratch, LEFT);
  }

And here is the part after the parsing where we use the Teensy's built in Keyboard emulation to plug the data right into the virtual terminal. Note how it takes the raw data from the track and uses Keyboard.print() to output it as well as tab through the browser entries.

  // FIND PAN
    uint8_t i=2;
    while ((track1[i] & 0x3F) != 0x3E) {
#ifdef SERIAL
        Serial.print((track1[i] & 0x3F)+0x20, BYTE); 
#endif
#ifdef KEYBOARD
        Keyboard.print((track1[i] & 0x3F)+0x20, BYTE);
#endif
      i++;
    }
...
#ifdef KEYBOARD
      Keyboard.print('\t');
      Keyboard.print(m1, BYTE);
      Keyboard.print(m2, BYTE);
      Keyboard.print(y1, BYTE);
      Keyboard.print(y2, BYTE);
    
      Keyboard.print('\t'); // tab to amount
      Keyboard.print('\t'); // tab to invoice
      Keyboard.print('\t'); // tab to description
      Keyboard.print("HOPE conference kits from Adafruit.com");
      Keyboard.print('\t'); // tab to customer ID
      Keyboard.print('\t'); // tab to first name
      Keyboard.print(fname);
      Keyboard.print('\t'); // tab to last name
      Keyboard.print(lname);
      
      for (uint8_t i=0; i<5; i++) {
        Keyboard.set_modifier(MODIFIERKEY_SHIFT);
        Keyboard.set_key1(KEY_TAB);
        Keyboard.send_now();
        Keyboard.set_modifier(0);
        Keyboard.set_key1(0);
        Keyboard.send_now();
      }

#endif

    beep(PIEZO, 4000, 200);
Once it's been swiped, the form is filled automatically, tabbing between the entries and then back-tabbing to the amount box so that can be filled out.

This guide was first published on Apr 21, 2013. It was last updated on Apr 21, 2013.

This page (Code Snippets) was last updated on Jan 06, 2023.

Text editor powered by tinymce.