// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright (c) 2026 Ashwin Whitchurch, Protocentral Electronics

/*
 * 05_ProximitySensing - Proximity / touch sensing on CH0
 *
 * Copyright (c) 2026 Ashwin Whitchurch, Protocentral Electronics
 * Email: info@protocentral.com
 *
 * Simple capacitive-touch / proximity detector on the ProtoCentral FDC2214:
 *   1. On startup, average a few hundred samples to establish a baseline.
 *   2. Each loop, compute the delta between the current reading and the
 *      baseline.
 *   3. When the delta exceeds a threshold, declare a "near" event.
 *
 * The baseline drifts slowly using an exponential moving average so that
 * long-term temperature/humidity drift does not trigger false detects.
 *
 * This software is licensed under the MIT License.
 */

//////////////////////////////////////////////////////////////////////////////////////////
//
//    Hardware Setup:
//      Connect a metal/foil electrode in series with a small inductor (e.g.
//      18 uH) and parallel cap (e.g. 33 pF) between IN0A and IN0B.
//        3.3V -> VCC
//        GND  -> GND
//        SDA  -> SDA (A4 on Uno)
//        SCL  -> SCL (A5 on Uno)
//
/////////////////////////////////////////////////////////////////////////////////////////

#include <Wire.h>
#include <Protocentral_FDC2214.h>

FDC2214 fdc;

const uint16_t BASELINE_SAMPLES   = 200;
const uint32_t PROXIMITY_THRESH   = 8000;       // raw counts; tune for your electrode
const float    BASELINE_DRIFT_A   = 0.001f;     // 0.0 = frozen baseline, 1.0 = no baseline

float baseline = 0.0f;

void setup() {
    Serial.begin(115200);
    while (!Serial && millis() < 3000);

    Wire.begin();

    if (!fdc.begin()) {
        Serial.println(F("FDC2214 not found"));
        while (1) delay(1000);
    }

    fdc.configureDefaults();
    fdc.setActiveChannel(FDC2214_CH0);
    fdc.setAutoscan(false);
    fdc.start();

    // Establish baseline.
    Serial.print(F("Calibrating baseline"));
    double sum = 0.0;
    for (uint16_t i = 0; i < BASELINE_SAMPLES; i++) {
        while (!fdc.isDataReady(FDC2214_CH0)) { /* wait */ }
        sum += (double)fdc.readRawChannel(FDC2214_CH0);
        if ((i % 20) == 0) Serial.print('.');
    }
    baseline = (float)(sum / BASELINE_SAMPLES);
    Serial.println();
    Serial.print(F("Baseline raw: "));
    Serial.println(baseline, 0);
    Serial.println(F("delta\tnear"));
}

void loop() {
    if (!fdc.isDataReady(FDC2214_CH0)) return;

    uint32_t raw   = fdc.readRawChannel(FDC2214_CH0);
    long delta     = (long)raw - (long)baseline;
    bool isNear    = (delta < 0) ? ((uint32_t)(-delta) > PROXIMITY_THRESH)
                                 : ((uint32_t)delta   > PROXIMITY_THRESH);

    Serial.print(delta);
    Serial.print('\t');
    Serial.println(isNear ? 1 : 0);

    // Slowly let the baseline track ambient drift only when no proximity event.
    if (!isNear) {
        baseline = baseline + BASELINE_DRIFT_A * ((float)raw - baseline);
    }
}
