#include <Wire.h>
//#define WIRE Wire
#define WIRE Wire1

#include "util.h"

void setup() {
  pinMode(28,OUTPUT);
  digitalWrite(28,HIGH);    //supply power
  Serial.begin(115200);
  // Wait for serial port to connect
  while(!Serial) {}
  delay(2000);
  //for PICO or others with settable pins
  WIRE.setSDA(26);
  WIRE.setSCL(27);
  Serial.println("TAG Programming Interface.");
  WIRE.begin();
  if (!tag.begin(WIRE)){
    Serial.println(F("ST25 not detected."));
    Serial.println(F("Try to reconnect and then reboot microcontroller."));
  }else{
    Serial.println(F("ST25 found on I2C."));
  }
  showMenu();
  tag.st25_io.readWriteChunkSize=16;    //32 fails on K parts due to timeout (K parts have 4-byte blocks, KC parts have 16 byte blocks)
}

void loop() {
  uint8_t b;
  uint16_t a;
  uint8_t d;  //address and data
  bool ccRes=false;
  s=scanSerial();
  int i;
  char* t;
  int cTemp;
  int i0,i1;
  if(s){
    //Serial.println(s);
    if(s[0]==0){showMenu();}
    if(s[0]==3){showMenu();}  //cancelled
    if(s[0]=='~'){rp2040.reboot();}
    if(s[0]=='o'){
      cTemp=tag.st25_io.readWriteChunkSize;
      tag.st25_io.readWriteChunkSize=32;  //to write in one pass
      tag.openI2CSession(password);
      tag.st25_io.readWriteChunkSize=cTemp;
      Serial.print(F("I2C session is "));
      Serial.println(tag.isI2CSessionOpen() ? "opened." : "closed.");
    }
    if(s[0]=='r'){
      if(s[1]=='1'){readNDEF(1);}      //choose record to read
      else if(s[1]=='2'){readNDEF(2);}
      else if(s[1]=='3'){readNDEF(3);}
      else if(s[1]=='4'){readNDEF(4);}
      else{                             //or read all
        readNDEF(1);
        readNDEF(2);
        readNDEF(3);
        readNDEF(4);
      }
    }
    if(s[0]=='i'){
      getInfo();
    }
    if(s[0]=='c'){
      decodeCC();
    }
    if(s[0]=='l'){
      if(tag.isI2CSessionOpen()){
        if((s[1]>='0')&&(s[1]<='3')){
          b=(s[1]-'0')&3;
          Serial.printf("Are you sure you want to change the RF lock bits to %d?\r\n",b);
          if(confirm()){
            setRFLock(b);
          }
        }else{
          Serial.println("Enter 0-3 after l.");
        }
      }else{
        Serial.println("Please open the session with 'o' before changing write access.");
      }
    }
    if(s[0]=='a'){
      Serial.println("Decoding Capability Container and NDEF Header.");
      decodeCCQuiet();
      i0=0;               //default to all messages
      i1=MESSAGE_COUNT;   
      if((s[1]>'0')&&(s[1]<('1'+MESSAGE_COUNT))){   //pick one message
        i0=s[1]-'1';  //offset of 1
        i1=i0+1;
      }
      for(i=i0;i<i1;i++){
        if(messageAdd[i]>0){
          Serial.printf("%2d: 0x%04x %4d bytes long.\r\n",i+1,messageAdd[i],messageLen[i]);
          if(messageLen[i]){decodeMessage(messageAdd[i],messageLen[i]);}
        }else{
          Serial.printf("%2d: Not present\r\n",i+1);
        }                  
      }            
    }
    if(s[0]=='e'){
      Serial.println("Confirm erase:");
      if(confirm()){
        eraseAll();
        i=tag.getMemoryAreaEndAddress(1);
        if(i){
          ccRes=writeCCfile(i);
          if(ccRes){
            Serial.println("CC written successfully.");
            if(tag.writeNDEFEmpty()){
              Serial.println("Blank NDEF record written successfully.");
            }else{
              Serial.println("Blank NDEF write failed.");
            }
          }else{
            Serial.println("CC write failed.");
          }
        }else{
          Serial.println("Get memory size failed.");
        }
      }else{
        Serial.println("\r\nErase cancelled.");
      }
    }
    if(s[0]=='d'){  //raw read of memory
      readRaw();
    }
    if(s[0]=='s'){  //raw dump of system
      readSys();
    }
    if(s[0]=='w'){  //write WiFi NDEF
      if(s[1]=='t'){
        Serial.println("Enter text for text tag.");
        t=getTxt();
        if(t){
          writeText(t);
        }else{
          Serial.println("\r\nEntry cancelled.");
        }
      }else if(s[1]=='w'){
        writeWiFi();
      }else if(s[1]=='u'){
        writeURI();
      }else if(s[1]=='v'){
        writeVcard();
      }else if(s[1]=='m'){
        writetextMime();
      }else if(s[1]=='b'){
        writeBinaryMime();
      }else{
        Serial.println("Please enter an option after 'w'.");
      }
    }
    if(s[0]=='h'){  //write raw hex to EEPROM
      a=0;d=0;
      if((unhex(s[1])>=0)&&(unhex(s[2])>=0)&&(unhex(s[3])>=0)&&(unhex(s[4])>=0)&&(unhex(s[5])>=0)&&(unhex(s[6])>=0)){
        a=unhex(s[1])*4096+unhex(s[2])*256+unhex(s[3])*16+unhex(s[4]);
        i=tag.getMemoryAreaEndAddress(1);
        if((a<0)||(a>i)){
          Serial.println("Address out of range.");
        }else{
          d=unhex(s[5])*16+unhex(s[6]);
          Serial.printf("Confirm write 0x%02x to 0x%04x?\r\n",d,a);
          if(confirm()){
            if(tag.writeEEPROM(a,&d,1)){
              Serial.println("Write OK.");
            }else{
              Serial.println("Write failed.");  
            }
          }else{
            Serial.println("Cancelled.");
          }
        }
      }else{
        Serial.println("Hex decode error.");
      }
    }
  }
}
