       if (row == CARD_ROWS)
       {
         state = STATE_END;
-        //Serial.println(state);
       }
       else
       {
         state = STATE_WAITING_ROW;
-        //Serial.println(state);
       }
     break;
     
     case STATE_END:
       // wait here until card removal
       // Note, later version will read on way out again, and complare in and out readings
-      if ((freg == 1) && (now == 0xFF))
+      if ((freg == REG_HOLE) && (now == ALL_HOLES))
       {
         sendCardReport(REPORT_OK_CARD, card, CARD_ROWS);
         state = STATE_NOCARD;
-        //Serial.println(state);
       }
     break;
     

}


char tohexch(byte val)
{
  val = val & 0x0F;


typedef enum 
{
  STATE_NOCARD        = 0,
  STATE_INSERTING,    //1
  STATE_WAITING_ROW,  //2
  STATE_IN_ROW,       //3
  STATE_GAP,          //4
  STATE_REMOVING,     //5
  STATE_END           //6
} STATE;

//===== LOCAL DATA ===============================================================================

static byte sticky = 0;
static boolean seenReg = false;
static byte row = 0;
static byte card[CARD_ROWS];
static STATE state = STATE_NOCARD;
static STATE prev = STATE_NOCARD;


//------------------------------------------------------------------------------------------------

void setup()
{
  Serial.begin(115200);  
  pinMode(LED_REG, OUTPUT);
  pinMode(LED_D7,  OUTPUT);
  pinMode(REG, INPUT);
  pinMode(D7,  INPUT);
  
  digitalWrite(LED_REG, HIGH);
  delay(1000);
  digitalWrite(LED_REG, LOW);
  
  digitalWrite(LED_D7, HIGH);
  delay(1000);
  digitalWrite(LED_D7, LOW);
  
  //pinMode(LED_D6,  OUTPUT);
  //pinMode(LED_D5,  OUTPUT);
  //pinMode(LED_D4,  OUTPUT);
  //pinMode(LED_D3,  OUTPUT);
  //pinMode(LED_D2,  OUTPUT);
  //pinMode(LED_D1,  OUTPUT);
  //pinMode(LED_D0,  OUTPUT);
  sendCardReport(REPORT_OK_BOOT, NULL, 0);
}


//------------------------------------------------------------------------------------------------

void loop()
{  
  //readPins
  byte freg = (digitalRead(REG) ? REG_PAPER : REG_HOLE);
  //TODO: read from PORTB as a single byte
  //TODO: run through crossbar if pins need remapping
  byte now  = (digitalRead(D7)  ? ALL_PAPER : ALL_HOLES);

  // Show live diagnostics on LEDs
  writeLEDs(freg, now);


  // crank round the acquisition state machine
  switch (state)
  {
    case STATE_NOCARD:
      // stay here while freg=hole and data=all holes (card removed)
      if ((freg == REG_PAPER) || now != ALL_HOLES)
      { // at least one sensor has seen paper
        state = STATE_INSERTING;
      } 
    break;
    
    case STATE_INSERTING:
      // check for early removal (all holes)
      if ((freg == REG_HOLE) && (now == ALL_HOLES))
      {
        // bail early if all on (removed)
        state = STATE_REMOVING;
      }
      // wait for all paper
      else if ((freg == REG_PAPER) && (now == ALL_PAPER))
      {
        row = 0;
        state = STATE_WAITING_ROW;
      }
    break;
    
    case STATE_WAITING_ROW:
      // check for early card removal (all reading holes)
      if ((freg == REG_HOLE) && (now == ALL_HOLES))
      {
        state = STATE_REMOVING;
      }
      else
      { // wait for any data to start appearing (at least one hole)
        if ((freg == REG_HOLE) || (now != ALL_PAPER))
        {
          sticky  = ~now; // 0=>hole, so we want to set bits for holes
          state   = STATE_IN_ROW;
        }
      }
    break;
    
    case STATE_IN_ROW:
      // check for early card removal (all holes)
      if ((freg == REG_HOLE) && (now == ALL_HOLES))
      {
        state = STATE_REMOVING;
      }
      else
      {
        // remember if we see the registration hole while reading a row
        // this is only punched if the row is completely unpunched
        // that way we don't miss the row
        if (freg == REG_HOLE)
        {
          seenReg = true;
        }
        // keep collecting sticky bits until all go zero again
        sticky |= ~now; // 0=>hole, so we want to collect 1's for holes
        if ((freg == REG_PAPER) && (now == ALL_PAPER))
        {
          state = STATE_GAP;
        }  
      }
    break;
