#pragma once #include "Config.h" struct AxisCal { int16_t min, center, max; // raw ADC counts }; // Processed stick values, -1000..1000 per logical axis (see StickAxis): // X + = right, Y + = forward, TWIST + = counterclockwise. struct StickFrame { int16_t v[NUM_AXES] = {}; bool allCentered(int16_t tolerance) const; }; class Sticks { public: // Loads calibration from EEPROM (or Config defaults), then captures the // resting center of each axis. Returns false if a stick looked deflected // at power-on (center capture skipped for that axis). bool begin(); void update(); // read + filter + map all axes const StickFrame& frame() const { return frame_; } int16_t raw(int axis) const { return (int16_t)filtered_[axis]; } const AxisCal& cal(int axis) const { return cal_[axis]; } // Sweep calibration: start, move every stick to all its limits, release // all sticks, then save. Output is held at zero while calibrating. void startCalibration(); bool saveCalibration(); // false = sweep too small, nothing saved void cancelCalibration(); bool calibrating() const { return calibrating_; } void resetCalibrationToDefaults(); // also clears EEPROM void printCalibration(Stream& s) const; // paste-able into Config.h private: AxisCal cal_[NUM_AXES]; AxisCal sweep_[NUM_AXES]; float filtered_[NUM_AXES] = {}; StickFrame frame_; bool calibrating_ = false; int16_t readAveraged(int axis, int samples); int16_t mapAxis(int axis, float raw) const; void applyDefaults(); bool loadFromEeprom(); void saveToEeprom(); };