#include <Wire.h>

// TCS34725 I2C address
#define TCS34725_ADDR 0x29

// Command bit to indicate command register
#define CMD_BIT 0x80

// Register addresses
#define REG_ENABLE          0x00
#define REG_ATIME           0x01
#define REG_WTIME           0x03
#define REG_AILTL           0x04
#define REG_AILTH           0x05
#define REG_AIHTL           0x06
#define REG_AIHTH           0x07
#define REG_INTERRUPT       0x16
#define REG_CONTROL         0x0F

// ENABLE register bits
#define ENABLE_PON          0x01  // Power ON
#define ENABLE_AEN          0x02  // ADC Enable
#define ENABLE_WEN          0x08  // Wait Enable
#define ENABLE_AIEN         0x10  // ALS Interrupt Enable

// INTERRUPT register bits
#define AIEN_CLEAR_LOW     0x01  // Interrupt on clear low
#define AIEN_CLEAR_HIGH    0x02  // Interrupt on clear high

const int interruptPin = 2;          // Digital pin connected to INT
volatile bool interruptFlag = false; // Flag set by ISR

// ISR to handle interrupt from TCS34725
void IRAM_ATTR handleInterruptISR() {
  interruptFlag = true;
}

// Function to write an 8-bit value to a register
void writeRegister(uint8_t reg, uint8_t value) {
  Wire.beginTransmission(TCS34725_ADDR);
  Wire.write(CMD_BIT | reg); // Command bit
  Wire.write(value);
  Wire.endTransmission();
}

// Function to read an 8-bit value from a register
uint8_t readRegister(uint8_t reg) {
  Wire.beginTransmission(TCS34725_ADDR);
  Wire.write(CMD_BIT | reg);
  Wire.endTransmission(false); // Restart
  Wire.requestFrom(TCS34725_ADDR, (uint8_t)1);
  if (Wire.available()) {
    return Wire.read();
  }
  return 0xFF; // Return invalid value if not available
}

// Function to write a 16-bit value to a register (little endian)
void writeRegister16(uint8_t reg, uint16_t value) {
  Wire.beginTransmission(TCS34725_ADDR);
  Wire.write(CMD_BIT | reg);
  Wire.write((uint8_t)(value & 0xFF));       // Low byte
  Wire.write((uint8_t)((value >> 8) & 0xFF)); // High byte
  Wire.endTransmission();
}

// Function to read a 16-bit value from a register (little endian)
uint16_t readRegister16(uint8_t reg) {
  Wire.beginTransmission(TCS34725_ADDR);
  Wire.write(CMD_BIT | reg);
  Wire.endTransmission(false); // Restart
  Wire.requestFrom(TCS34725_ADDR, (uint8_t)2);
  if (Wire.available() >= 2) {
    uint16_t value = Wire.read();
    value |= (Wire.read() << 8);
    return value;
  }
  return 0xFFFF; // Return invalid value if not available
}

void setup() {
  Serial.begin(9600);
  Wire.begin();

  // Initialize interrupt pin
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterruptISR, FALLING);
  
  // Power on the sensor (activate PON)
  writeRegister(REG_ENABLE, ENABLE_PON);
  delay(3); // Wait for oscillator to stabilize

  // Enable ADC (AEN)
  writeRegister(REG_ENABLE, ENABLE_PON | ENABLE_AEN);
  
  // Set integration time (ATIME)
  // Example: 700ms integration time
  // ATIME register: 256 - (integration_time / 2.4ms)
  // 700ms / 2.4ms ≈ 291
  // 256 - 291 = -35 → Wrap around to 221 (0xDD)
  writeRegister(REG_ATIME, 0xDD); // Adjust as necessary

  // Set gain (CONTROL register)
  // 0x00: 1x, 0x01: 4x, 0x02: 16x, 0x03: 60x
  writeRegister(REG_CONTROL, 0x00); // 1x gain

  // Set interrupt thresholds
  uint16_t clearThresholdLow = 100;    // Example low threshold
  uint16_t clearThresholdHigh = 0xFFFF; // Example high threshold (no upper limit)

  writeRegister16(REG_AILTL, clearThresholdLow);  // Low threshold low byte
  writeRegister16(REG_AIHTL, clearThresholdHigh); // High threshold low byte

  // Configure interrupt on clear low
  writeRegister(REG_INTERRUPT, AIEN_CLEAR_LOW);

  // Enable interrupt in ENABLE register (AIEN)
  uint8_t enable = readRegister(REG_ENABLE);
  enable |= ENABLE_AIEN; // Set AIEN bit
  writeRegister(REG_ENABLE, enable);
  
  Serial.println("TCS34725 initialized and interrupt configured.");
}

void loop() {
  if (interruptFlag) {
    // Clear the flag
    interruptFlag = false;
    
    Serial.println("Interrupt detected: Clear value below threshold.");

    // Read clear channel value
    uint16_t clear = readRegister16(0x14); // CDATAL and CDATAH
    Serial.print("Clear Value: ");
    Serial.println(clear);
    
    // Optional: Take additional actions here, such as logging or adjusting sensor settings

    // Optionally reset the interrupt by toggling AIEN
    uint8_t enable = readRegister(REG_ENABLE);
    enable &= ~ENABLE_AIEN; // Disable AIEN
    writeRegister(REG_ENABLE, enable);
    delay(10); // Small delay
    enable |= ENABLE_AIEN; // Enable AIEN
    writeRegister(REG_ENABLE, enable);
  }

  // Optional: Regular sensor readings
  /*
  uint16_t clear, red, green, blue;
  clear = readRegister16(0x14);
  red   = readRegister16(0x16);
  green = readRegister16(0x18);
  blue  = readRegister16(0x1A);
  
  Serial.print("C: "); Serial.print(clear);
  Serial.print(" R: "); Serial.print(red);
  Serial.print(" G: "); Serial.print(green);
  Serial.print(" B: "); Serial.println(blue);
  
  delay(1000);
  */
}
use adafruits library instead of this, and for the ISR, check the clear ranges once again. if it is between x and y, return 1, else if it is between a and b, return 0