#define bitWrite_f(value, bit, bitvalue) ((bitvalue) ? ((value) |= (1UL << (bit))) : ((value) &= ~(1UL << (bit))))

const int LATCH_PIN = D2;
const int CLOCK_PIN = D3;
const int DATA_PIN = D4;

    uint8_t* registerState;
    size_t COUNT_74HC595 = 3; // Number of 74HC595
    int PIN_PER_IC = 8;



void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Hello, STM32!");



    //Initialize array
  // registerState = new byte[numOfRegisters];
  registerState = (uint8_t*) malloc(COUNT_74HC595 * sizeof(uint8_t));
  for (size_t i = 0; i < COUNT_74HC595; i++) {
    registerState[i] = 0;
  }
    //memset(registerState, 0, numOfRegisters * sizeof(uint8_t));  // Initialize to 0

  //set pins to output so you can control the shift register
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);


  
}

void loop() {
  // put your main code here, to run repeatedly:
  registerWrite_f(0, HIGH);
  registerWrite_f(7, HIGH);
  registerWrite_f(8, HIGH);
  registerWrite_f(16, HIGH);
  //  registerWrite_f(23, HIGH);

  delay(2000); // this speeds up the simulation

  registerWrite_f(0, LOW);
  registerWrite_f(7, LOW);
  registerWrite_f(8, LOW);
  registerWrite_f(16, LOW);

  
  // delay(1000); // this speeds up the simulation
}



void registerWrite_f(int pin, int state) { // Function for array shifing bitwise

 int totalPins = COUNT_74HC595 * PIN_PER_IC;  // Total pins across all shift registers
  int which_74HC595 = pin / PIN_PER_IC;      // Determine which register the pin belongs to. which IC
  int physical_pin = pin % PIN_PER_IC;      // Determine which pin within the register (0-7)

    // Update the state of the specified pin in the correct register
  if (which_74HC595 >= COUNT_74HC595) {
    Serial.println("Error: Register index out of bounds.");
    return;
  }

  // Only update the specified pin in the correct register
  bitWrite_f(registerState[which_74HC595], physical_pin, state);

  digitalWrite(LATCH_PIN, LOW);  //Begin session

  // Send the state of all registers to the shift register chain
   for (int i = (COUNT_74HC595 - 1); i >= 0; i--) { // loop into each IC-74HC595  DESC - int i = 0; i < numOfRegisters; i++ 

    Serial.print("Shift register ");
        Serial.print(i);
        Serial.print(" state: ");
        Serial.println(registerState[i], BIN); // Print state in binary

    shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, registerState[i]);
    
    }

  digitalWrite(LATCH_PIN, HIGH); //End session

}

// Manual shiftOut function with a slight delay
void shiftOutManual(int dataPin, int clockPin, int bitOrder, uint8_t val) {
  for (int i = 0; i < 8; i++)  {
    if (bitOrder == LSBFIRST) {
      digitalWrite(dataPin, !!(val & (1 << i)));
    } else {
      digitalWrite(dataPin, !!(val & (1 << (7 - i))));
    }

    // Pulse the clock
    digitalWrite(clockPin, HIGH);
    delayMicroseconds(100);  // Short delay to ensure timing (can be adjusted)
    digitalWrite(clockPin, LOW);
    delayMicroseconds(100);  // Short delay to ensure timing (can be adjusted)
  }
}
74HC595
74HC595
74HC595