// =============================================================
//  QPAD-XIAO (Seeed XIAO RP2040) — Step 1: screen + pads test
//  HTMAA 2026 — "embedded programming" week
//  Shows the raw value of each touch pad on the OLED
//  and in the Serial Monitor, to calibrate the touch threshold.
// =============================================================
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// ---------- SSD1306 OLED screen, 128x64, over I2C ----------
#define SCREEN_W 128
#define SCREEN_H 64
#define OLED_ADDR 0x3C          // usual I2C address (sometimes 0x3D)
Adafruit_SSD1306 display(SCREEN_W, SCREEN_H, &Wire, -1);

// ---------- Touch pads ----------
// Board silkscreen: Q0[D10] Q1[D9] Q2[D8] Q3[D1] Q4[D7] Q5[D0]
// XIAO -> RP2040 GPIO mapping:
//   D10=GPIO3  D9=GPIO4  D8=GPIO2  D1=GPIO27  D7=GPIO1  D0=GPIO26
const int N_PADS = 6;
const int padPins[N_PADS]  = { 3, 4, 2, 27, 1, 26 };            // Q0..Q5
const char* padNames[N_PADS] = { "Q0 A", "Q1 B", "Q2 bas", "Q3 gau", "Q4 dro", "Q5 haut" };

int baseline[N_PADS];           // resting value, measured at startup
const int MARGIN = 10;          // to adjust after looking at the values!

// "Step response" capacitive measurement:
// discharge the pad to 0 V, then let it charge back up through
// the internal pull-up and count how many loops that takes.
// A finger adds capacitance -> it charges back more slowly.
int readPad(int pin) {
  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);
  delayMicroseconds(10);
  int t = 0;
  noInterrupts();
  pinMode(pin, INPUT_PULLUP);
  while (!digitalRead(pin) && t < 5000) t++;
  interrupts();
  return t;
}

int readPadAvg(int pin) {
  long sum = 0;
  for (int k = 0; k < 8; k++) sum += readPad(pin);
  return sum / 8;
}

bool isTouched(int i) {
  return readPadAvg(padPins[i]) > baseline[i] + MARGIN;
}

void setup() {
  Serial.begin(115200);

  Wire.setSDA(6);               // D4 = GPIO6 = SDA
  Wire.setSCL(7);               // D5 = GPIO7 = SCL
  Wire.begin();

  if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
    Serial.println("Ecran introuvable (essaie 0x3D)");
    while (true) delay(100);
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.println("QPAD test");
  display.println("Calibration...");
  display.println("Ne touche rien !");
  display.display();
  delay(500);

  // Calibration: resting average of each pad
  for (int i = 0; i < N_PADS; i++) {
    long sum = 0;
    for (int k = 0; k < 16; k++) sum += readPadAvg(padPins[i]);
    baseline[i] = sum / 16;
  }
}

void loop() {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.println("pad    val base");

  for (int i = 0; i < N_PADS; i++) {
    int v = readPadAvg(padPins[i]);
    bool touched = v > baseline[i] + MARGIN;

    display.print(padNames[i]);
    display.setCursor(48, display.getCursorY());
    display.print(v);
    display.setCursor(78, display.getCursorY());
    display.print(baseline[i]);
    if (touched) display.print(" <");
    display.println();

    Serial.print(padNames[i]); Serial.print(":"); Serial.print(v);
    Serial.print(i < N_PADS - 1 ? "\t" : "\n");
  }
  display.display();
  delay(50);
}
