# Scans the I2C bus to discover connected sensor devices and their 7-bit bus addresses.

from machine import Pin, SoftI2C

# I2C bus pin configuration (SoftI2C allows using any GPIO pins on RP2040)
I2C_SDA_PIN = 16  # GP16 (SDA data line)
I2C_SCL_PIN = 17  # GP17 (SCL clock line)

# Initialize SoftI2C bus at standard 100 kHz clock frequency
i2c = SoftI2C(sda=Pin(I2C_SDA_PIN), scl=Pin(I2C_SCL_PIN), freq=100000)

print("=" * 55)
print("  UBI - I2C SENSOR BUS SCANNER")
print(f"  Pins: SDA = GP{I2C_SDA_PIN}, SCL = GP{I2C_SCL_PIN}")
print("=" * 55)

# Scan all 7-bit I2C addresses in the valid range 0x08 to 0x77 (8 to 119)
devices = i2c.scan()

# Known laboratory components used in UBI coursework
KNOWN_DEVICES = {
    0x3C: "OLED Display 0.91'' (SSD1306, 128x32)",
    0x3D: "OLED Display (SSD1306 alternative address)",
    0x23: "BH1750 Ambient Light Sensor / Luxmeter",
    0x10: "VEML7700 Precision Light Sensor",
    0x57: "MAX30102 / MAX30100 PPG Pulse Oximeter",
    0x38: "AHT20 Temperature and Humidity Sensor",
    0x76: "BMP280 Barometric Pressure Sensor (SDO -> GND)",
    0x77: "BMP280 Barometric Pressure Sensor (SDO -> 3V3)",
    0x68: "BMI160 6-Axis IMU (Accelerometer + Gyro)",
    0x0D: "QMC5883L 3-Axis Magnetometer",
    0x29: "VL53L0X Laser ToF Distance Sensor",
    0x5A: "MLX90614 Non-Contact Infrared Thermometer"
}

if len(devices) == 0:
    print("\n[!] No I2C devices found.")
    print("    Troubleshooting:")
    print("    1. Verify power supply connections (3.3V and GND).")
    print("    2. Verify SDA and SCL wiring (do not cross lines).")
    print("    3. Check for external pull-up resistors on the bus.")
else:
    print(f"\n[OK] I2C devices found: {len(devices)}")
    for device in devices:
        hex_addr = hex(device)
        hint = KNOWN_DEVICES.get(device, "Unknown device / custom module")
        print(f"  -> Address: {hex_addr} (dec: {device:3d}) | {hint}")
print("=" * 55)
