Thanks for all the suggestions so far.
based on the advice I opted for a non-isr based solution in order to have more consistent timing. All reads and writes are done directly via port manipulation and I have tried to reduce/minimise the logic used.
When I created a test system that limited the operations to one mode (for all channels) I was able to get speeds that were actually quite acceptable. Once I added back all the necessary conditional logic and modes the timing got too delayed again.
I have attached my code with the hopes someone can see some clever ways to squeeze more speed out of it but I am beginning to lose hope. I think I may have to create an all digital logic system based on discrete flipflops and logic ICs in order to get the tight timing I need.
#define FASTADC 1
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
/*
//bits used
//PINC
#define EOA1 0
#define EOA2 1
#define EOA3 2
#define EOA4 3
//PINB
#define EOC1 2
#define EOC2 3
#define EOC3 4
#define EOC4 5
//PIND
#define TRIG1 0
#define TRIG2 1
#define TRIG3 2
#define TRIG4 3
//PORTD
#define GATE1 4
#define GATE2 5
#define GATE3 6
#define GATE4 7
*/
//DIGITAL INPUT PINS
#define EOA1pin 14
#define EOA2pin 15
#define EOA3pin 16
#define EOA4pin 17
byte EOApin[] = {EOA1pin, EOA2pin, EOA3pin, EOA4pin};
#define EOC1pin 10
#define EOC2pin 11
#define EOC3pin 12
#define EOC4pin 13
byte EOCpin[] = {EOC1pin, EOC2pin, EOC3pin, EOC4pin};
#define TRIG1pin 0
#define TRIG2pin 1
#define TRIG3pin 2
#define TRIG4pin 3
byte TRIGpin[] = {TRIG1pin, TRIG2pin, TRIG3pin, TRIG4pin};
#define QUADSWApin 8
#define QUADSWBpin 9
//ANALOG INPUT PINS
#define MODESW1pin 4
#define MODESW2pin 5
#define MODESW3pin 6
#define MODESW4pin 7
byte MODESWpin[] = {MODESW1pin, MODESW2pin, MODESW3pin, MODESW4pin};
//DIGITAL OUTPUT PINS
#define GATE1pin 4
#define GATE2pin 5
#define GATE3pin 6
#define GATE4pin 7
byte GATEpin[] = {GATE1pin, GATE2pin, GATE3pin, GATE4pin};
#define AR 0
#define AD 1
#define LOOP 2
#define OFF 0
#define ON 1
byte mode[4] = {AR,AR,AR,AR};
byte prevMode[4] = {AR,AR,AR,AR};
byte quadMode[2] = {OFF, OFF};
#define SWITCHPOLLTIME 500
byte count = 0;
void setup() {
#if FASTADC
// set prescale to 16
sbi(ADCSRA,ADPS2) ;
cbi(ADCSRA,ADPS1) ;
cbi(ADCSRA,ADPS0) ;
#endif
for (int i = 0; i<4; i++) {
pinMode(EOApin[i], INPUT);
// digitalWrite(EOApin[i], LOW);
pinMode(EOCpin[i], INPUT);
// digitalWrite(EOCpin[i], LOW);
pinMode(TRIGpin[i], INPUT);
//digitalWrite(TRIGpin[i], LOW);
pinMode(GATEpin[i], OUTPUT);
}
pinMode(QUADSWApin, INPUT);
pinMode(QUADSWBpin, INPUT);
digitalWrite(QUADSWApin, HIGH);
digitalWrite(QUADSWBpin, HIGH);
}
unsigned long time = 0;
unsigned long prevTime = 0;
void loop() {
time = millis();
// this timer condition calls a function that checks the state of 6 mode switches. It is called periodically since a slow response is ok and checking it eats up processing time
//The counter inside is set so that every time it is called it only checks one of the 4 switches,
if ((time-prevTime) > 50) {
count = (count+1) %4;
modeSW_update(count);
prevTime = time;
quadSW_update();
}
if (quadMode[0] == ON) {
//if bitRead(PIND,0) bitClear(PORTD, 4); //TRIG1 trigger to start GATE1
if bitRead(PINB,3) bitSet(PORTD, 4); //EOC2 trigger to start GATE1
if bitRead(PINC, 0) bitSet(PORTD, 5); //EOA1 trigger start GATE2
if bitRead(PINC, 1) bitClear(PORTD, 4); //EOA2 trigger stop GATE1
if bitRead(PINB,2) bitClear(PORTD, 5); //EOC1 trigger to stop GATE2
// if bitRead(PINB,3) bitClear(PORTD, 4); //EOC2 trigger to start GATE1
} else {
if (mode[0] == LOOP) { if bitRead(PINB,2) bitSet(PORTD, 4); }
if (mode[1] == LOOP) { if bitRead(PINB,3) bitSet(PORTD, 5); }
if (mode[0] == AR) {
if bitRead(PIND,0) bitSet(PORTD, 4); else bitClear(PORTD, 4);
} else {
if (!bitRead(PORTD,4) && bitRead(PIND, 0) ) bitSet(PORTD,4);
if bitRead(PINC, 0) bitClear(PORTD, 4);
}
if (mode[1] == AR) {
if bitRead(PIND,1) bitSet(PORTD, 5); else bitClear(PORTD, 5);
} else {
if (!bitRead(PORTD,5) && bitRead(PIND, 1) ) bitSet(PORTD,5);
if bitRead(PINC, 1) bitClear(PORTD, 5);
}
}
if (quadMode[1] == ON) {
//if bitRead(PIND,3) bitSet(PORTD, 6); //TRIG1 trigger to start GATE1
if bitRead(PINB,5) bitSet(PORTD, 6); //EOC2 trigger to start GATE1
if bitRead(PINC, 2) bitSet(PORTD, 7); //EOA1 trigger start GATE2
if bitRead(PINC, 3) bitClear(PORTD, 6); //EOA2 trigger stop GATE1
if bitRead(PINB,4) bitClear(PORTD, 7); //EOC1 trigger to stop GATE2
} else {
if (mode[2] == LOOP) { if bitRead(PINB,4) bitSet(PORTD, 6); }
if (mode[3] == LOOP) { if bitRead(PINB,5) bitSet(PORTD, 7); }
if (mode[2] == AR) {
if bitRead(PIND,2) bitSet(PORTD, 6); else bitClear(PORTD, 6);
} else {
if (!bitRead(PORTD,6) && bitRead(PIND, 2) ) bitSet(PORTD,6);
if bitRead(PINC, 2) bitClear(PORTD, 6);
}
if (mode[3] == AR) {
if bitRead(PIND,3) bitSet(PORTD, 7); else bitClear(PORTD, 7);
} else {
if (!bitRead(PORTD,7) && bitRead(PIND, 3) ) bitSet(PORTD,7);
if bitRead(PINC, 3) bitClear(PORTD, 7);
}
}
}
void modeSW_update(byte cnt) {
int val;
val = analogRead(MODESWpin[cnt]);
if (val < 10) mode[cnt] = AD;
else if ( (val >= 10) && (val < 400) ) { mode[cnt] = AR; }
else //if (val >= 400) mode[cnt] = LOOP;
mode[cnt] = LOOP;
}
void quadSW_update() {
quadMode[0] = !bitRead(PINB,0);
quadMode[1] = !bitRead(PINB,1);
}