/*
 * Écriture d'un bloc MIFARE Classic — Kaihatsu Lab
 * Écrit un texte de 16 caractères maximum dans le bloc 4, puis relit le bloc pour vérifier.
 *
 * ATTENTION : n'écris jamais dans le bloc 0 ni dans un « sector trailer » (blocs 3, 7, 11, 15...).
 * Le trailer contient les clés et les droits d'accès : une erreur peut rendre le secteur définitivement illisible.
 */
#include <SPI.h>
#include <MFRC522.h>

const uint8_t PIN_SS  = 5;
const uint8_t PIN_RST = 22;
const byte    BLOCK   = 4;
const char    TEXT[]  = "KAIHATSU LAB";  // 16 caractères maximum

MFRC522 rfid(PIN_SS, PIN_RST);
MFRC522::MIFARE_Key key;

void setup() {
  Serial.begin(115200);
  SPI.begin(18, 19, 23, PIN_SS);
  rfid.PCD_Init();
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

  if (BLOCK == 0 || (BLOCK % 4) == 3) {
    Serial.println(F("Bloc interdit : choisis un bloc de donnees (4, 5, 6, 8, 9, 10...)."));
    while (true) delay(1000);
  }
  Serial.println(F("Approche une carte MIFARE Classic pour ecrire..."));
}

void loop() {
  if (!rfid.PICC_IsNewCardPresent() || !rfid.PICC_ReadCardSerial()) return;

  MFRC522::StatusCode status = rfid.PCD_Authenticate(
      MFRC522::PICC_CMD_MF_AUTH_KEY_A, BLOCK, &key, &(rfid.uid));

  if (status == MFRC522::STATUS_OK) {
    byte data[16] = {0};
    size_t n = strlen(TEXT);
    if (n > 16) n = 16;
    memcpy(data, TEXT, n);

    status = rfid.MIFARE_Write(BLOCK, data, 16);
    if (status == MFRC522::STATUS_OK) {
      byte check[18];
      byte size = sizeof(check);
      if (rfid.MIFARE_Read(BLOCK, check, &size) == MFRC522::STATUS_OK && memcmp(check, data, 16) == 0) {
        Serial.println(F("Ecriture verifiee."));
      } else {
        Serial.println(F("Ecriture faite, mais la relecture ne correspond pas."));
      }
    } else {
      Serial.print(F("Ecriture impossible : "));
      Serial.println(rfid.GetStatusCodeName(status));
    }
  } else {
    Serial.print(F("Authentification refusee : "));
    Serial.println(rfid.GetStatusCodeName(status));
  }

  rfid.PICC_HaltA();
  rfid.PCD_StopCrypto1();
}
