can you check the following code for errors? 
#include <esp_now.h>
#include <pgmspace.h>

// Define the slave address used for I2C communication
#define SLAVE_ADDRESS 0x10

// Define the SPI pins
#define I2C_SDA_PIN 4  // Example I2C SDA pin
#define I2C_SCL_PIN 5  // Example I2C SCL pin
#define SPI_CS_PIN 15  // Example SPI Chip Select pin
#define SPI_MISO_PIN 19  // Example SPI MISO pin
#define SPI_MOSI_PIN 23  // Example SPI MOSI pin
#define SPI_CLK_PIN 18  // Example SPI CLK pin

// Define the GPIO pins
#define GPIO_PIN1 4
#define GPIO_PIN2 16

// Define the number of bytes in the buffers
#define BUFFER_SIZE 32
unsigned char gpioBuffer[BUFFER_SIZE];
unsigned char i2cBuffer[BUFFER_SIZE];
unsigned char spiBuffer[BUFFER_SIZE];

// Define all program info and versioning identifiers into rom
const static char pname[] PROGMEM = "Klipper Controller.\n";
const static char author[] PROGMEM = "Marcel Hofstra.\n";
const static char version[] PROGMEM = "Klipper Controller, ESP32 controller V1.0 Beta.\n";
const static char serial[] PROGMEM = "202325081346v1b\n";


// Define the buffer for GPIO inputs/outputs
uint8_t gpioBuffer[2];

// Define the buffer for I2C inputs/outputs
uint8_t i2cBuffer[BUFFER_SIZE];

// Define the buffer for SPI inputs/outputs
uint8_t spiBuffer[BUFFER_SIZE];

// Declare the interrupt handler functions
void IRAM_ATTR gpioInterrupt1();
void IRAM_ATTR gpioInterrupt2();

// Define the threshold for ESPNow reliability
const int RESEND_THRESHOLD = 3;

// Define the structure that holds the ESPNow data
typedef struct attribute((packed)) {
  uint8_t retryCount;
  uint8_t buffer[BUFFER_SIZE];
} EspNowData;

// Define the callback function for ESPNow message reception
void OnDataRecv(const uint8_t* macAddr, const uint8_t* data, int dataLen) {
  // Check the data length and MAC address
  if (dataLen != sizeof(EspNowData) || macAddr == NULL) {
    return;
  }

  EspNowData* recvData = (EspNowData*)data;

  // Process the received buffer
  // Buffer type can be determined by the sender and receiver
  // For example, if ‘bufferType’ is 1, it’s the GPIO buffer
  // If ‘bufferType’ is 2, it’s the I2C buffer, and so on…

  int bufferType = recvData->buffer[0];

  switch (bufferType) {
    case 1: // GPIO buffer
      memcpy(gpioBuffer, recvData->buffer + 1, BUFFER_SIZE - 1);
      break;
    case 2: // I2C buffer
      memcpy(i2cBuffer, recvData->buffer + 1, BUFFER_SIZE - 1);
      break;
    case 3: // SPI buffer
      memcpy(spiBuffer, recvData->buffer + 1, BUFFER_SIZE - 1);
      break;
    default:
      break;
  }
}

void setup() {
  // Initialize GPIO pins as inputs
  pinMode(GPIO_PIN1, INPUT);
  pinMode(GPIO_PIN2, INPUT);

  // Initialize Interrupt Service Routines (ISRs)
  attachInterrupt(digitalPinToInterrupt(GPIO_INT_PIN1), gpioInterrupt1, CHANGE);
  attachInterrupt(digitalPinToInterrupt(GPIO_INT_PIN2), gpioInterrupt2, CHANGE);

// Initialize I2C interface with hardware interrupt
  Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
  Wire.onReceive(i2cInterruptHandler);

  // Initialize SPI interface with hardware interrupt
  SPI.begin(SPI_CLK_PIN, SPI_MISO_PIN, SPI_MOSI_PIN, SPI_CS_PIN);
  SPI.usingInterrupt(digitalPinToInterrupt(SPI_CLK_PIN));
  attachInterrupt(digitalPinToInterrupt(SPI_CLK_PIN), spiInterruptHandler, RISING);


  // Initialize ESP-NOW
  WiFi.mode(WIFI_STA);
  if (esp_now_init() != ESP_OK) {
    // Handle ESP-NOW initialization error
  }

  // Register ESP-NOW send callback function
  esp_now_register_send_cb(sendData);

  // Register ESP-NOW receive callback function
  esp_now_register_recv_cb(receiveData);
}
}

void loop() {
  // Check if there is any data in the buffers to be sent
  // Buffer type can be changed accordingly (1: GPIO, 2: I2C, 3: SPI)
  if (gpioBufferHasData()) {
    EspNowData data;
    data.retryCount = 0;
    data.buffer[0] = 1; // Buffer type

    memcpy(data.buffer + 1, gpioBuffer, BUFFER_SIZE - 1);

    sendBufferToSlave(data);
  }

  if (i2cBufferHasData()) {
    EspNowData data;
    data.retryCount = 0;
    data.buffer[0] = 2; // Buffer type

    memcpy(data.buffer + 1, i2cBuffer, BUFFER_SIZE - 1);

    sendBufferToSlave(data);
  }

  if (spiBufferHasData()) {
    EspNowData data;
    data.retryCount = 0;
    data.buffer[0] = 3; // Buffer type

    memcpy(data.buffer + 1, spiBuffer, BUFFER_SIZE - 1);

    sendBufferToSlave(data);
  }

  delay(1000);
}
// Callback function for handling I2C interrupt
void IRAM_ATTR i2cInterruptHandler() {
  // Add your I2C interrupt code here
}

// Callback function for handling SPI interrupt
void IRAM_ATTR spiInterruptHandler() {
  // Add your SPI interrupt code here
}

// GPIO Interrupt handlers
void IRAM_ATTR gpioInterrupt1() {
  // Read the state of GPIO pin 1 and update the gpioBuffer accordingly
  gpioBuffer[0] = digitalRead(GPIO_PIN1);
  gpioBuffer[1] = 0; // Placeholder for any other GPIO pin(s)
}

void IRAM_ATTR gpioInterrupt2() {
  // Read the state of GPIO pin 2 and update the gpioBuffer accordingly
  gpioBuffer[1] = digitalRead(GPIO_PIN2);
  gpioBuffer[0] = 0; // Placeholder for any other GPIO pin(s)
}

// Check if there is any data in the GPIO buffer
bool gpioBufferHasData() {
  for (int i = 0; i < 2; i++) {
    if (gpioBuffer[i] != 0) {
      return true;
    }
  }
  return false;
}

// Check if there is any data in the I2C buffer
bool i2cBufferHasData() {
  // Check the corresponding condition for I2C buffer data presence
  // For example, if using an I2C sensor and i2cBuffer as output
  // Return true if i2cBuffer[0] != 0;
  return false;
}

// Check if there is any data in the SPI buffer
bool spiBufferHasData() {
  // Check the corresponding condition for SPI buffer data presence
  // For example, if using SPI module and spiBuffer as output
  // Return true if spiBuffer[0] != 0;
  return false;
}

// Function to send data over ESP-NOW
void sendData(const uint8_t* macAddress, const uint8_t* buffer, size_t size) {
  esp_err_t result = esp_now_send(macAddress, buffer, size);
  // Handle error (if any)
}

// Function to receive data over ESP-NOW
void receiveData(const uint8_t* macAddress, const uint8_t* buffer, size_t size) {
  // Handle received data here
}