title: MFRC 522 with ATmega8. Mifare Classic 1K won't authenticate
body: <p>I have a problem with an ATmega8 and Mifare RC-522 based NFC/RFID controller.</p>
  
  <p>I'm using <a href="https://labitat.dk/wiki/RFID_RC522-AN" rel="nofollow">this library</a> and I've managed to read the UID of a card.</p>
  
  <p>However, I'd like to also read and write other parts of the card but whenever I try to use the <code>MFRC522_Auth</code> function I don't get the idle interrupt which I should, instead it gives me <code>LoAlertIrq</code> saying that <code>FIFObuffer</code> is almost empty.</p>
  
  <p>Here are the docs for the <a href="http://www.nxp.com/documents/data_sheet/MFRC522.pdf" rel="nofollow">reader</a> and the <a href="http://www.nxp.com/documents/data_sheet/MF1S503x.pdf" rel="nofollow">card</a>, and below are relevant parts of my code.</p>
  
  <p>main.c :</p>
  
  <pre><code>byte = mfrc522_request(PICC_REQALL,str);
  if(byte == CARD_FOUND)
  {
      byte = mfrc522_get_card_serial(str);
      if(byte == CARD_FOUND)
      {
          byte = mfrc522_auth(PICC_AUTHENT1A, 7, sectorKeyA, str);
          if( (byte == CARD_FOUND) )
          {
              byte = MFRC522_Read1(4, str);
              if(byte == CARD_FOUND)
              {
                  //write content of that block
              }
      }
  }
  </code></pre>
  
  <p>Relevant functions from the library :</p>
  
  <pre><code>void mfrc522_write(uint8_t reg, uint8_t data)
  {
      ENABLE_CHIP();
      spi_transmit((reg&lt;&lt;1)&amp;0x7E);
      spi_transmit(data);
      DISABLE_CHIP();
  }
  
  uint8_t mfrc522_read(uint8_t reg)
  {
      uint8_t data;
      ENABLE_CHIP();
      spi_transmit(((reg&lt;&lt;1)&amp;0x7E)|0x80);
      data = spi_transmit(0x00);
      DISABLE_CHIP();
      return data;
  }
  
  uint8_t mfrc522_to_card(uint8_t cmd, uint8_t *send_data, uint8_t send_data_len, uint8_t *back_data, uint32_t *back_data_len)
  {
      uint8_t status = 0;
      uint8_t irqEn = 0x00;
      uint8_t waitIRq = 0x00;
      uint8_t lastBits;
      uint8_t n;
      uint8_t tmp;
      uint32_t i;
  
      switch (cmd)
      {
          case MFAuthent_CMD:     //Certification cards close
          {
              irqEn = 0x12;
              waitIRq = 0x10;
              break;
          }
          case Transceive_CMD:    //Transmit FIFO data
          {
              irqEn = 0x77;
              waitIRq = 0x30;
              break;
          }
          default:
              break;
      }
  
      mfrc522_write(ComIEnReg, irqEn|0x80);   //Interrupt request
      n=mfrc522_read(ComIrqReg);
      mfrc522_write(ComIrqReg,n&amp;(~0x80));//clear all interrupt bits
      n=mfrc522_read(FIFOLevelReg);
      mfrc522_write(FIFOLevelReg,n|0x80);//flush FIFO data
     // mfrc522_write(CommandReg, Idle_CMD);  //NO action; Cancel the current cmd???
  
      n=mfrc522_read(CommandReg);
      mfrc522_write(CommandReg,n|0x00);
  
      //Writing data to the FIFO
      for (i=0; i&lt;send_data_len; i++)
      {
          mfrc522_write(FIFODataReg, send_data[i]);
      }
  
  
      //Execute the cmd
      mfrc522_write(CommandReg, cmd);
      if (cmd == Transceive_CMD)
      {
          n=mfrc522_read(BitFramingReg);
          mfrc522_write(BitFramingReg,n|0x80);
      }
  
  
      //Waiting to receive data to complete
      i = 2000;   //i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms???
      while (1) {
          n = mfrc522_read(ComIrqReg);    // ComIrqReg[7..0] bits are: Set1 TxIRq RxIRq IdleIRq   HiAlertIRq LoAlertIRq ErrIRq TimerIRq
  
          if (n &amp; waitIRq) {                  // One of the interrupts that signal success has been set.
              break;
          }
          if (n &amp; 0x01) {                     // Timer interrupt - nothing received in 25ms
  //          return 6; //debug purpose
              if (cmd == MFAuthent_CMD) {
                          LCD_Clear();
                          LCD_WriteTextXY(1, 3, LCD_itoa( mfrc522_read(ComIrqReg) ) );
                          _delay_ms(2500);
                      }
              break;
          }
          if (--i == 0) {                     // The emergency break. If all other condions fail we will eventually terminate on this one after 35.7ms. Communication with the MFRC522 might be down.
              if (cmd == MFAuthent_CMD) {
                  LCD_Clear();
                  LCD_WriteTextXY(1, 3, LCD_itoa( mfrc522_read(ComIrqReg) ) );
                  _delay_ms(2500);
              }
              break;
          }
      }
  
  
      tmp=mfrc522_read(BitFramingReg);
      mfrc522_write(BitFramingReg,tmp&amp;(~0x80));
  
      if (i != 0)
      {
          if(!(mfrc522_read(ErrorReg) &amp; 0x1B))    //BufferOvfl Collerr CRCErr ProtecolErr
          {
              status = CARD_FOUND;
              if (n &amp; irqEn &amp; 0x01)
              {
                  status = CARD_NOT_FOUND;            //??
              }
  
              if (cmd == Transceive_CMD)
              {
                  n = mfrc522_read(FIFOLevelReg);
                  lastBits = mfrc522_read(ControlReg) &amp; 0x07;
                  if (lastBits)
                  {
                      *back_data_len = (n-1)*8 + lastBits;
                  }
                  else
                  {
                      *back_data_len = n*8;
                  }
  
                  if (n == 0)
                  {
                      n = 1;
                  }
                  if (n &gt; MAX_LEN)
                  {
                      n = MAX_LEN;
                  }
  
                  //Reading the received data in FIFO
                  for (i=0; i&lt;n; i++)
                  {
                      back_data[i] = mfrc522_read(FIFODataReg);
                  }
              }
          }
  
          if (cmd == MFAuthent_CMD) {
              LCD_WriteTextXY(1, 10, LCD_itoa16( mfrc522_read(Status2Reg) ) );
              _delay_ms(2500);
          }
      } else status = 9;
  
  
      return status;
  }
  
  
  uint8_t mfrc522_get_card_serial(uint8_t * serial_out)
  {
      uint8_t status;
      uint8_t i;
      uint8_t serNumCheck=0;
      uint32_t unLen;
  
      mfrc522_write(BitFramingReg, 0x00);     //TxLastBists = BitFramingReg[2..0]
  
      serial_out[0] = PICC_ANTICOLL;
      serial_out[1] = 0x20;
      status = mfrc522_to_card(Transceive_CMD, serial_out, 2, serial_out, &amp;unLen);
  
      if (status == CARD_FOUND)
      {
          //Check card serial number
          for (i=0; i&lt;4; i++)
          {
              serNumCheck ^= serial_out[i];
          }
          if (serNumCheck != serial_out[i])
          {
              status = ERROR;
          }
      }
      return status;
  }
  
  uint8_t mfrc522_auth(uint8_t authMode, uint8_t BlockAddr, uint8_t *Sectorkey, uint8_t *serNum)
  {
      uint8_t status;
      uint32_t recvBits;
      uint8_t i;
      uint8_t buff[12];
  
   // Validate instruction block address + sector + password + card serial number
      buff[0] = authMode;
      buff[1] = BlockAddr;
      for (i=0; i&lt;6; i++)
      {
          buff[i+2] = 0xFF /**(Sectorkey+i)*/;
      }
      for (i=0; i&lt;4; i++)
      {
          buff[i+8] = *(serNum+i);
      }
  
      status = mfrc522_to_card(MFAuthent_CMD, buff, 12, buff, &amp;recvBits);
  
      return status;
  }
  
  uint8_t MFRC522_Read1(uint8_t blockAddr, uint8_t *recvData)
  {
      uint8_t status = 0;
      uint8_t unLen, efa;
  
      recvData[0] = PICC_READ;
      recvData[1] = blockAddr;
      CalculateCRC(recvData, 2, &amp;recvData);
      status = mfrc522_to_card(Transceive_CMD, recvData, 4, recvData, &amp;unLen);
  
      if ((status != CARD_FOUND)|| (unLen != 0x90))
      {
          status = ERROR;
      }
  
      return status;
  }
  
  uint8_t CalculateCRC(uint8_t *pIndata, uint8_t len, uint8_t *pOutData)
  {
      uint8_t i, n;
      uint8_t status = 0;
  
      n = mfrc522_read(DivIrqReg);
      mfrc522_write(DivIrqReg,n&amp;(~0x04));         //CRCIrq = 0
      n = mfrc522_read(FIFOLevelReg);         //FIFO
      mfrc522_write(FIFOLevelReg, n|0x80);
      //Write_MFRC522(CommandReg, PCD_IDLE);
  
      // Write data to the FIFO
      for (i=0; i&lt;len; i++)
      {
          mfrc522_write(FIFODataReg, *(pIndata+i));
      }
      mfrc522_write(CommandReg, CalcCRC_CMD);
  
      // Read the CRC calculation result
      i = 0xFF;
  
      while(1){
          n = mfrc522_read(DivIrqReg);
  
          if (n &amp; 0x04) {
              break;
          }
  
          if (--i != 0) {
              return 7;
          }
      }
  
      // Read the CRC calculation result
      pOutData[3] = mfrc522_read(CRCResultReg_2);
      pOutData[4] = mfrc522_read(CRCResultReg_1);
  
      return status = 0;
  }
  </code></pre>