/* ======      Deklarasi Library MFRC522 beserta konstanta terkait    ===== */
#include <SPI.h>      //include library SPI
#include <MFRC522.h>  //include library untuk RFID RC522
#define SS_PIN 10  //pin 10 terhubung ke pin SS pd modul RFID RC522
#define RST_PIN 9  //pin 9 terhubung ke pin Reset pd modul RFID RC522

//membuat struktur MIFARE_Key diberi nama 'key' yg akan menyimpan informasi kartu
MFRC522::MIFARE_Key key;          
MFRC522 mfrc522(SS_PIN, RST_PIN); //membuat nama objek mfrc522

/*  ========  deklarasi variabel dan konstanta untuk Penulisan  ========   */
int block=60; //nomor blok '60' dimana kita akan menulis & membaca data
//variabel array dengan 16 byte utk ditulis ke satu dari 64 blok yg tersedia
byte blockcontent[16] = {"Board ArduinoUno"};  //menulis "Board ArduinoUno"
//buka baris berikut jika akan menghapus 1 blok
//byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  
byte readbackblock[18]; //array ini digunakan untuk membaca satu blok

void setup() {
  Serial.begin(9600);        //init komuniaksi serial
  SPI.begin();               //init SPI bus
  mfrc522.PCD_Init();        //init kartu MFRC522 (PCD= Proximity Coupling Device)
  Serial.println("Scan kartu MIFARE Classic anda ");
  
  //persiapan "security key" utk fungsi tulis & baca
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;  //keyByte is defined in the "MIFARE_Key" 'struct' definition in the .h file of the library
  }
}

void loop()  {  
  if ( ! mfrc522.PICC_IsNewCardPresent() || ! mfrc522.PICC_ReadCardSerial()) {
    return; //keluar ke baris terakhir jika tidak ada kartu didekatkan
  }
  Serial.println("card selected");      
  writeBlock(block, blockcontent);   //menulis blockcontent ke nomor blok tertentu
  readBlock(block, readbackblock);   //membaca blockcontent dari nomr blok tertentu
  //hapus '//' dibawah ini jika anda ingin melihat isi 1KB dg blok yg telah ditulis
  //mfrc522.PICC_DumpToSerial(&(mfrc522.uid)); //menampilkan semua data kartu
   
  Serial.print("baca blok: ");
  for (int j=0 ; j<16 ; j++) {
    Serial.write (readbackblock[j]); //tampilkan isi dari satu blok
  }
  Serial.println("");
}
  
/*  --------------------   Fungsi menulis spesifik blok   --------------------  */
int writeBlock(int blockNumber, byte arrayAddress[]) //deklarasi fungsi beserta kedua var
{
  int largestModulo4Number=blockNumber;//deklarasi var beserta kaitannya dg blockNumber
  int trailerBlock=largestModulo4Number+3;//deklarasi var trailerBlock 
  if (blockNumber > 2 && (blockNumber+1)%4 == 0) { //menentukan blok trailer
    Serial.print(blockNumber);Serial.println(" ini adalah blok trailer:");
    return 3;  //keluar ke baris terakhir
  }
  Serial.print(blockNumber);  //tampilkan pada Serial Monitor nomor blok
  Serial.println(" ini adalah nomor blok data:");
  
  //pemeriksaan status dari blok yg ingin diakses
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) { //jika status tidak STATUS_OK eksekusi baris 67-68
    Serial.print("PCD_Authenticate() gagal: "); 
    Serial.println(mfrc522.GetStatusCodeName(status));//tampilkan status error
    return 3;//return "3" sbg error message dan lompat menuju baris terakhir
  }
  //menulis blok 
  status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print("MIFARE_Write() gagal: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 4;//return "4" sbg error message dan lompat menuju baris terakhir
  }
  Serial.println("block sudah ditulis... "); 
}

/*  --------------------  Fungsi membaca spesifik blok   --------------------  */
int readBlock(int blockNumber, byte arrayAddress[]) //deklarasi fungsi beserta kedua var
{
  int largestModulo4Number=blockNumber;
  int trailerBlock=largestModulo4Number+3;//deklarasi variabel trailerBlock

//pemeriksaan dari blok yg diinginkan untuk akses
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print("PCD_Authenticate() : ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 3;//return "3" sebagai error message dan lompat menuju baris terakhir
  }

//membaca satu blok  
byte buffersize = 18;//we need to define a variable with the read buffer size, since the MIFARE_Read method below needs a pointer to the variable that contains the size... 
status = mfrc522.MIFARE_Read(blockNumber, arrayAddress, &buffersize);//&buffersize is a pointer to the buffersize variable; MIFARE_Read requires a pointer instead of just a number
  if (status != MFRC522::STATUS_OK) {
    Serial.print("MIFARE_read() ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 4;//return "4" sebagai error message dan lompat menuju baris terakhir
  }
  Serial.println("blok telah dibaca");
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5