#include <I2cDiscreteIoExpander.h>
#include <SoftwareSerial.h>
#include "ModbusRTUMaster.h"
#include <EEPROM.h>

#define Trig_A0   3
#define Trig_A1   4
#define Trig_A2   5
#define Trig_A3   6
#define Trig_A4   7
#define Trig_A5   8
#define Open 0
#define Close 1
uint8_t Room = 8;
uint8_t Floor    = 4;
uint16_t F_state[6];
bool Rstate[8];
const uint32_t baudRates[8] = {1200, 2400, 4800, 9600, 16200, 38400, 57600, 115200};
static uint16_t room_state[6]={0xffff,0xffff,0xffff,0xffff,0xffff,0xffff} ;
const int baudEEPROMAddress = 0;
const uint8_t rxPin    = 14;
const uint8_t txPin    = 10;
const uint8_t dePin    = 12;
//const uint8_t rxPin    = 10;
//const uint8_t txPin    = 11;
//const uint8_t dePin    = 8;
//uint16_t F_state[4]={0B0000000000000111,0,0,0};
SoftwareSerial mySerial(rxPin, txPin);
ModbusRTUMaster modbus(mySerial, dePin); // serial port, driver enable pin for rs-485 (optional)
I2cDiscreteIoExpander device[6] = {0,1,2,3,4,5};


void writeMultipleCoils(uint8_t id, uint16_t startAddress, bool *buf, uint16_t quantity){
  if (modbus.writeMultipleCoils(id ,startAddress,buf,quantity)){
    
    Serial.print(F("WroteComplete"));
  }
  else processError();
}

void processError() {
  if (modbus.getTimeoutFlag()) {
    Serial.println(F("Communication timed out"));
    modbus.clearTimeoutFlag();
  }
  else if (modbus.getExceptionResponse() != 0) {
    Serial.print(F("Received exception response: "));
    Serial.print(modbus.getExceptionResponse());
    switch (modbus.getExceptionResponse()) {
      case 1:
        Serial.println(F(" - Illegal function"));
        break;
      case 2:
        Serial.println(F(" - Illegal data address"));
        break;
      case 3:
        Serial.println(F(" - Illegal data value"));
        break;
      case 4:
        Serial.println(F(" - Server device failure"));
        break;
      default:
        Serial.println();
        break;
    }
    modbus.clearExceptionResponse();
  }
  else {
    Serial.println("An error occurred");
  }
}

void ByteToBools(uint16_t value)
{
   
  Rstate[0] = (value & 1) == 0 ? false : true;
  Rstate[1] = (value & 2) == 0 ? false : true;
  Rstate[2] = (value & 4) == 0 ? false : true;
  Rstate[3] = (value & 8) == 0 ? false : true;
  Rstate[4] = (value & 16) == 0 ? false : true;
  Rstate[5] = (value & 32) == 0 ? false : true;
  Rstate[6] = (value & 64) == 0 ? false : true;
  Rstate[7] = (value & 128) == 0 ? false : true;
  Rstate[8] = (value & 256) == 0 ? false : true;
  Rstate[9] = (value & 512) == 0 ? false : true;
  Rstate[10] = (value & 1024) == 0 ? false : true;
  Rstate[11] = (value & 2048) == 0 ? false : true;
  Rstate[12] = (value & 4096) == 0 ? false : true;
  Rstate[13] = (value & 8192) == 0 ? false : true;
  Rstate[14] = (value & 16348) == 0 ? false : true;
  Rstate[15] = (value & 32768) == 0 ? false : true;
}

void action(int id, uint16_t room ,int state){

 Serial.print(" R"); Serial.print(id+1);
   
switch (room){
        case 0x1:  Serial.print("01"); break;        
        case 0x2:  Serial.print("02"); break;
        case 0x4:  Serial.print("03"); break;
        case 0x8:  Serial.print("04"); break;
        case 0x10:  Serial.print("05"); break;
        case 0x20:  Serial.print("06"); break;
        case 0x40:  Serial.print("07"); break;
        case 0x80:  Serial.print("08"); break;
        case 0x100:  Serial.print("09"); break;       
        case 0x200:  Serial.print("10"); break;
        case 0x400:  Serial.print("11"); break;
        case 0x800:  Serial.print("12"); break;
        case 0x1000:  Serial.print("13"); break;
        case 0x2000:  Serial.print("14"); break;
        case 0x4000:  Serial.print("15"); break;
        case 0x8000:  Serial.print("16"); break;
        
      }
  if(state == 0){
  Serial.println(" Open # ");
 }else Serial.println(" Close # ");
}

void setup()
{
 ///--------------- insert -------------- 
 Serial.begin(9600);
  Serial.setTimeout(100);
  while(!Serial) {}
    Serial.println(F("ModbusRTUMasterProbe"));
    uint32_t baud;
    EEPROM.get(baudEEPROMAddress, baud);
    if (baud == 0xFFFFFFFF) {
      baud = 38400;
      EEPROM.put(baudEEPROMAddress, baud);
   }
  modbus.begin(baud); // modbus baud rate, config (optional)
  modbus.setTimeout(100);
  Serial.print(F("Modbus serial port configuration: "));
  Serial.print(baud);
  Serial.println(F("-8-N-1"));
  Serial.println();
  //--------------- insert --------------
  pinMode(Trig_A0, INPUT_PULLUP);
  pinMode(Trig_A1, INPUT_PULLUP);
  pinMode(Trig_A2, INPUT_PULLUP);
  pinMode(Trig_A3, INPUT_PULLUP);
  pinMode(Trig_A4, INPUT_PULLUP);
  pinMode(Trig_A5, INPUT_PULLUP);
  // initialize i2c interface
  Wire.begin();
  // initialize serial interface
  Serial.begin(9600);
  device[0].disableBitwiseInversion();
  device[1].disableBitwiseInversion();
  device[2].disableBitwiseInversion();
  device[3].disableBitwiseInversion();
  device[4].disableBitwiseInversion();
  device[5].disableBitwiseInversion();
  delay(1000);
  Serial.println("Clearing any int/mirroring inputs");
  //CHECK start port status -------------- 
  mirrorInputOntoOutputs(0);
  mirrorInputOntoOutputs(1);
  mirrorInputOntoOutputs(2);
  mirrorInputOntoOutputs(3);
  mirrorInputOntoOutputs(4);
  mirrorInputOntoOutputs(5);
  //CHECK start port status --------------

}

uint16_t getChangedInputValue(uint8_t idx) {
    device[idx].digitalRead();
    return device[idx].getPorts();
}

void mirrorInputOntoOutputs(uint8_t idx) {
    uint16_t Act_room;
    int Rstate;
    uint16_t bothports = getChangedInputValue(idx);
    uint16_t inputs = lowByte(bothports);
    // Mirror the inputs to the outputs
    // leave the inputs, as inputs (i.e. writing high)
    //uint16_t newValue = word(inputs, 0xffff) ; // (inputs << 8) | 0xff;
    Serial.print("Inputs read as 0x "); Serial.print(bothports, HEX);
    Serial.print(";  Room state     0x"); Serial.print(room_state[idx], HEX);
    //Serial.println(" being mirrored to out");
    F_state[idx] = bothports;

    if (room_state[idx] == bothports){
      Serial.println("  State = equal");
    }else if (room_state[idx] < bothports){
      Act_room = bothports - room_state[idx];
      Rstate = Close;
      action(idx,Act_room ,Rstate);
    }else if (room_state[idx] > bothports){
      Act_room = room_state[idx] - bothports ;
      Rstate = Open;
      action(idx,Act_room ,Rstate);
    }

   // device[idx].digitalWrite(newValue);
   // Serial.print("Wrote 2 bytes: port0 -> 0x");
   // Serial.print(lowByte(newValue), HEX);
   // Serial.print(" port1 -> 0x");
   // Serial.print(highByte(newValue), HEX);
   // Serial.print(" to device ");
   // Serial.println((int)idx);
       room_state[idx] = bothports;
}




void loop() {

  //======================== insert ================
// for(int i=0 ;i<Room;i++){   
//    ByteToBools(F_state[i]);
 //   writeMultipleCoils(i+1, 0,Rstate, Room);
 //  }
//======================== insert ================


    if (digitalRead(Trig_A0)== LOW){
      //Serial.println("int = 0");
      ByteToBools(F_state[0]);
      //Serial.print("TEST = "); Serial.print(F_state[0], HEX);
      writeMultipleCoils(1, 0,Rstate, Room);
      mirrorInputOntoOutputs(0);
    }
    if (digitalRead(Trig_A1)== LOW){
      ByteToBools(F_state[1]);
      writeMultipleCoils(2, 1,Rstate, Room);
      mirrorInputOntoOutputs(1);
    }
    if (digitalRead(Trig_A2)== LOW){
      ByteToBools(F_state[2]);
      writeMultipleCoils(3, 2,Rstate, Room);
      mirrorInputOntoOutputs(2);
    }
    if (digitalRead(Trig_A3)== LOW){
      ByteToBools(F_state[3]);
      writeMultipleCoils(4, 3,Rstate, Room);
      mirrorInputOntoOutputs(3);
    }
    if (digitalRead(Trig_A4)== LOW){
      ByteToBools(F_state[4]);
      writeMultipleCoils(5, 4,Rstate, Room);
      mirrorInputOntoOutputs(4);
    }
    if (digitalRead(Trig_A5)== LOW){
      ByteToBools(F_state[5]);
      writeMultipleCoils(6, 5,Rstate, Room);
      mirrorInputOntoOutputs(5);
    }
  
}


pcf8575Breakout
Address bits 001
pcf8575Breakout
Address bits 001
pcf8575Breakout
Address bits 001
pcf8575Breakout
Address bits 001
pcf8575Breakout
Address bits 001
pcf8575Breakout
Address bits 001