 #define NUM_CONN 3
 
 SoftwareSerial* bus[NUM_CONN];
-
 int RX[NUM_CONN] = {A1, A3, A5};
 int TX[NUM_CONN] = {A0, A2, A4};
+volatile uint8_t *rxPortRegister[NUM_CONN];
+uint8_t rxBitMask[NUM_CONN];
+int activeBus = -1;
+unsigned long listenStartTime = 0;
+#define listenTimeout 20
+
 int coil[NUM_CONN] = {6, 5, 10}; // magnets
 int distanceToSource[NUM_CONN] = {99, 99, 99};
 int shortestDistanceToSource;


void dropConnector() {
  // send out message that we're going to drop a connector
  char c = DROPPING_CONNECTOR;
  for (int i=0; i<NUM_CONN; i++) bus[i]->write(c);

  // pick random connected connector to drop
  // count number of ports with a low distance to source

  }

  for (int i=0; i<NUM_CONN; i++) distanceToSource[i] = 99;
  //addTimer(50, processEnergy);
}

uint8_t rxRead(int index) {
  return *rxPortRegister[index] & rxBitMask[index];
}

void txWrite(int index, int value) {
  // writeCounter++;
  // if(writeCounter < MAX_WRITES) return;
  if(SERIAL_DEBUG) {
    Serial.print("w");
    Serial.println(index);
  }
  // begin with pulse so other side can start listening
  digitalWrite(TX[index], LOW);
  delay(2);
  digitalWrite(TX[index], HIGH);
  bus[index]->write(value);
}

void setActiveBus(int index) {
  if(SERIAL_DEBUG) {
    Serial.print("l");
    Serial.println(index);
  }
  activeBus = index;
  listenStartTime = millis();
  bus[index]->listen();
}

void readActiveBus() {
  while(bus[activeBus]->available()) {
    if(SERIAL_DEBUG) {
      Serial.print("a");
      Serial.println(activeBus);
    }
    int message = int(bus[activeBus]->read());
    if(message != 0) {
      if(SERIAL_DEBUG) {
        Serial.print(activeBus);
        Serial.print(": ");
        Serial.println(message);
      }
      parseMessage(activeBus, message);
      activeBus = -1;
      break;
    }
  }
  if (millis()-listenStartTime > listenTimeout) {
    if(SERIAL_DEBUG) {
      Serial.print("t");
      Serial.println(activeBus);
    }
    activeBus = -1;
  }
}

void parseMessage(int busIndex, int message) {
  switch(message) {
    case ALERT: // button is pressed
      if (!isSource && !alertState) {
        // set alert state and set random timer
        alertState = true;
        alertTimer = addTimer(random(1000, 5000), dropConnector);
        // propagate signal though network
        for (int j=0; j<NUM_CONN; j++) if (j!=busIndex) txWrite(j, ALERT);
      }
      break;
    case DROPPING_CONNECTOR: // some connector in the network is dropped
      if(alertState) {
        // relax alert state and timer
        removeTimer(alertTimer); // cancel dropping connector
        alertState = false;
        // propagate signal though network
        for (int j=0; j<NUM_CONN; j++) if (j!=busIndex) txWrite(j, DROPPING_CONNECTOR);
      }
      break;
    default: // distance to source
      if (!isSource) {
        // if new distance is shorter, take that as distance to source for this port
        if (message<distanceToSource[busIndex]+1) distanceToSource[busIndex] = message+1;
        // if we are not connected (yet) and a new distance was received start timer to process energy
        // (hopefully this does enhances asynchronous updating between the nodes)
        // ToDo: why use timer here? can't it get triggered to much, shouldn't this simply debounce? why not call on fixed interval?
        if (shortestDistanceToSource == 99) addTimer(10, processEnergy);
      }
  }
}

void setup() {
  // set up pins
  for (int i=0; i<NUM_CONN; i++) {
    bus[i] = new SoftwareSerial(RX[i], TX[i]);
    bus[i]->begin(115200); //(9600); //1200
    pinMode(coil[i], OUTPUT);

    uint8_t port = digitalPinToPort(RX[i]);
    rxPortRegister[i] = portInputRegister(port);
    rxBitMask[i] = digitalPinToBitMask(RX[i]);
  }
  pinMode(leds1pin, OUTPUT);
  pinMode(leds2pin, OUTPUT);
