#ifndef MEASURE_H #define MEASURE_H #include "ADXL345FastSPI.h" // <-- zgodnie z main.cpp #include #include #include #include #include #include #include #include #include // Domyślne parametry akwizycji ADXL345 (mogą być nadpisane w // ADXL345FastSPI::begin) static constexpr uint32_t SPI_HZ = 5000000; // 5 MHz (MODE3) static constexpr float ODR_HZ = 3200.0f; // maks. ODR // Zakres ustawiany w main.cpp przez ADXL345FastSPI::begin(..., RANGE_2G, ...) struct FileInfo { String path; // np. "/3/00000057.wmt" uint64_t size; // bajty bool exists; // true, jeśli ostatni plik istnieje }; struct SpaceInfo { double value; const char *unit; // "GB" | "MB" | "UNKNOWN" }; class DataCapture { // --- Nagłówek pliku WMT --- struct FileHeader { char magic[3]; // "WMT" uint16_t version; // 1 uint16_t headerSize; // sizeof(FileHeader) uint32_t sampleSize; // sizeof(Sample) uint32_t timestamp; // UNIX startu akwizycji uint32_t reccount; // liczba rekordów Sample w pliku } __attribute__((packed)); public: // --- Rekord próbki --- struct Sample { uint32_t offset; // µs od startu akwizycji (wspólny dla ramki) uint8_t sensor_id; // 0..3 int16_t x, y, z; // surowe ADXL345 bool ready; // 1 = obecna } __attribute__((packed)); // Konstruktor dopasowany do main.cpp – przyjmuje ADXL345FastSPI DataCapture(ADXL345FastSPI &adxl, Display &display, RTC_DS3231 &rtc, fs::FS &storage, size_t bufferSize = 131072 /* 128 KB */); ~DataCapture(); bool capture(uint32_t captureSeconds, const char *filename); bool captureAuto(uint32_t captureSeconds, const char *baseDirectory = "/logs"); void printSamplingRate(uint32_t reccount, uint32_t captureSeconds, String filename); void readHeaderAndPrint(const char *path); void stop(); bool isActive() const { return measurementActive_; } // SD utils SpaceInfo freeSpaceMB(); float freeSpaceFloat(bool *isGB = nullptr); String unixToDateTime(uint32_t ts); // plik z najwyższym indeksem FileInfo getLastFileInfo(); bool deleteAllOnSD(); bool isExit = false; // true oznacza przerwanie pomiaru private: ADXL345FastSPI &adxl_; Display &display_; RTC_DS3231 &rtc_; fs::FS &_fs; // Katalogowanie const String _baseDir = "/"; const String _ext = ".wmt"; const uint8_t _digits = 8; const uint16_t _maxFilesPerDir = 400; // Bufor zapisu (PSRAM) uint8_t *buffer_ = nullptr; size_t bufferSize_ = 0; size_t bufferIndex_ = 0; bool measurementActive_ = false; bool flushToFile(File &f); static uint8_t crc8(const uint8_t *data, size_t len); void setTestingIndicator_(bool on, String myDir, String myFile); bool isEscape() { bool ispress = (GPIO.in & (1UL << BTN_OK)) == 0; if (ispress) { isExit = true; measurementActive_; display_.textStatus("Cancelling. Wait!"); } return ispress; } // szybkidigitalRead : czy BTN stop??? public: bool isAllDigits(const char *s); uint32_t toUint(const char *s); static const char *basenameFromPath(const char *full); bool isWmtWithDigits(const char *name, uint32_t &idxOut) const; String makeIndexedName(uint32_t idx) const; static String joinPath(const String &a, const String &b); bool ensureDir(uint32_t dirNum); uint32_t findHighestNumericDir(); void scanDirForWmt(uint32_t dirNum, uint32_t &count, uint32_t &highestIdx); bool recursiveDelete(const String &path); String dirPath(uint32_t dirNum) const; String allocateNextFilePath(); String generateNextFilename(); void printLastFileInfoSerial(); }; #endif // MEASURE_H