// https://forum.arduino.cc/t/create-code-for-arduino/1339715/140

/*
  Simplified Pseudocode:
  1. Initialize pins for the two injector banks.
  2. Use a timer to generate 5 ms pulses for each injector bank.
  3. Alternate between the two banks every 75 ms.

  alto777, DaveX, iocasa, koikeeper
  
  https://www.onallcylinders.com/wp-content/uploads/2016/03/16/common-firing-order-upd2.png
  Straight 6 firing order: 1-5-3-6-2-4
  https://carscounsel.com/wp-content/uploads/2024/06/Understanding-Straight-6-Firing-Order-768x432.jpg
  https://lambdageeks.com/wp-content/uploads/2021/10/6-cylinder.jpg
  Suck, Squeeze, Bang, Blow
  https://www.autoblueprint.com/1961_images/ART3/Inline_6_Cylinder_with_firing_order_1-5-3-6-2-4.gif

Power Exhaust Inject Compress (RED ORG CYN BLU)

Power - close E and I
Exhaust - open E valve
Inject - open I valve
Compress - close E and I

CAM SHAFT
- turns at 1/2 Crankshaft
= Valve pairs: (same angle)
Inject and  Exhaust (for example, both 180 degrees)
Power and Compress (for example, both 0 degrees)

V6 1 4
   2 5
   3 6

Crank Rotation Angle
CYL 120 240 360 480 600 720 
 1   P   -   E   I   -   C   
 4   C   P   -   E   I   - 
 3   -   C   P   -   E   I  
 6   I   -   C   P   -   E 
 2   E   I   -   C   P   -
 5   -   E   I   -   C   P

S6 123456 (straight six)

*/

unsigned long timer75, timeout75 = 75; // 75ms timer
unsigned long timer5, timeout5 = 5; // 5ms timer

bool bank = 1; // alternate banks, start with 1 to be negated on first loop()
byte bankApin[] = {11, 10, 9}; // A injectors
byte bankBpin[] = {6, 7, 8}; // B injectors
byte banksize = sizeof(bankApin)/sizeof(bankApin[0]);

int speed = 1; // 1 = normal speed (no printing), 10 = 1/10 speed // 100 is v e r y s l o w

volatile bool button2Pressed; // variable inside interrupt service routeine
volatile bool button3Pressed; // variable inside interrupt service routeine
int button2Pin = 2; // interrupt pin INT0
int button3Pin = 3; // interrupt pin INT1

void setup() {
  timeout75 *=  speed; // speed multiplier (to slow the timing for simulation)
  timeout5 *= speed; // speed multiplier (to slow the timing for simulation)

  Serial.begin(115200);

  pinMode(bankApin, OUTPUT); // configure pins
  pinMode(bankBpin, OUTPUT);
  digitalWrite(bankApin, LOW); // set pins LOW
  digitalWrite(bankBpin, LOW);

  pinMode(button2Pin, INPUT_PULLUP); // timing sensor
  pinMode(button3Pin, INPUT_PULLUP); // timing sensor
}

void loop() {
  if (millis() - timer75 > timeout75) { // every 75 milliseconds
    timer75 = millis(); // reset 75ms timer
    bank = !bank; // switch bank
    fire(bank); // fire bank
  }
}

void fire(byte bank) {
  if (speed > 1) { // if NOT full speed (1)
    Serial.write(bank + 65); // bank + ASCII 'A' = A or B
    Serial.print(1); // indicate injectors ON
  }

// sequence 
  for (int i = 0; i < banksize; i++) {
    if (bank)
      digitalWrite(bankApin[i], HIGH);
    else
      digitalWrite(bankBpin[i], HIGH);
  }

  if (millis() - timer5 > timeout5) { // wait for 5ms
    timer5 = millis(); // reset 5ms timer

    for (int i = 0; i < banksize; i++) {
      digitalWrite(bank + injectorPinStart, LOW); // bankA STOP firing
      if (speed > 1)
        Serial.print(0); // indicate injectors OFF
    }
  }
}

int button2ISR() { // Interrupt Service Routine called on a button press
  noInterrupts(); // disable interrupts while in the ISR
  button2Pressed = true; // set the flag that the button was pressed
  interrupts(); // enable interrupts when leaving the ISR
}

int button3ISR() { // Interrupt Service Routine called on a button press
  noInterrupts(); // disable interrupts while in the ISR
  button3Pressed = true; // set the flag that the button was pressed
  interrupts(); // enable interrupts when leaving the ISR
}
2T
58T
A
B
INT1
INT0
3
2
1
4
5
6
A4988
1
5
3
6
2
4