20260217_200901_z set RTC to GPS using 1PPS pulse-per-second discipline rtc-gps drift=-28 s 20260217_201001_z set RTC to GPS using 1PPS pulse-per-second discipline rtc-gps drift=+0 s 20260217_201119_z set RTC to GPS using 1PPS pulse-per-second discipline rtc-gps drift=+0 s 20260217_201219_z set RTC to GPS using 1PPS pulse-per-second discipline rtc-gps drift=+0 s
90 lines
2.3 KiB
C++
90 lines
2.3 KiB
C++
#pragma once
|
|
|
|
#include <Arduino.h>
|
|
#include <SD.h>
|
|
#include <SPI.h>
|
|
#include <Wire.h>
|
|
#include "tbeam_supreme_adapter.h"
|
|
|
|
enum class SdWatchState : uint8_t {
|
|
UNKNOWN = 0,
|
|
ABSENT,
|
|
MOUNTED
|
|
};
|
|
|
|
enum class SdEvent : uint8_t {
|
|
NO_CARD,
|
|
CARD_MOUNTED,
|
|
CARD_REMOVED
|
|
};
|
|
|
|
using SdStatusCallback = void (*)(SdEvent event, const char* message);
|
|
|
|
struct SdWatcherConfig {
|
|
bool enableSdRailCycle = true;
|
|
bool enablePinDumps = true;
|
|
bool recoveryRailCycleOnFullScan = true;
|
|
uint32_t recoveryRailOffMs = 250;
|
|
uint32_t recoveryRailOnSettleMs = 700;
|
|
uint32_t startupWarmupMs = 1500;
|
|
uint32_t pollIntervalAbsentMs = 1000;
|
|
uint32_t pollIntervalMountedMs = 2000;
|
|
uint32_t fullScanIntervalMs = 10000;
|
|
uint8_t votesToPresent = 2;
|
|
uint8_t votesToAbsent = 5;
|
|
};
|
|
|
|
class StartupSdManager {
|
|
public:
|
|
explicit StartupSdManager(Print& serial = Serial);
|
|
|
|
bool begin(const SdWatcherConfig& cfg, SdStatusCallback callback = nullptr);
|
|
void update();
|
|
|
|
bool isMounted() const { return watchState_ == SdWatchState::MOUNTED; }
|
|
SdWatchState state() const { return watchState_; }
|
|
|
|
bool consumeMountedEvent();
|
|
bool consumeRemovedEvent();
|
|
|
|
void printCardInfo();
|
|
bool ensureDirRecursive(const char* path);
|
|
bool rewriteFile(const char* path, const char* payload);
|
|
void permissionsDemo(const char* path);
|
|
|
|
private:
|
|
void logf(const char* fmt, ...);
|
|
void notify(SdEvent event, const char* message);
|
|
void forceSpiDeselected();
|
|
void dumpSdPins(const char* tag);
|
|
bool initPmuForSdPower();
|
|
void cycleSdRail(uint32_t offMs = 250, uint32_t onSettleMs = 600);
|
|
bool tryMountWithBus(SPIClass& bus, const char* busName, uint32_t hz, bool verbose);
|
|
bool mountPreferred(bool verbose);
|
|
bool mountCardFullScan();
|
|
bool verifyMountedCard();
|
|
const char* cardTypeToString(uint8_t type);
|
|
void setStateMounted();
|
|
void setStateAbsent();
|
|
|
|
Print& serial_;
|
|
SdWatcherConfig cfg_{};
|
|
SdStatusCallback callback_ = nullptr;
|
|
|
|
SPIClass sdSpiH_{HSPI};
|
|
SPIClass sdSpiF_{FSPI};
|
|
SPIClass* sdSpi_ = nullptr;
|
|
const char* sdBusName_ = "none";
|
|
uint32_t sdFreq_ = 0;
|
|
XPowersLibInterface* pmu_ = nullptr;
|
|
|
|
SdWatchState watchState_ = SdWatchState::UNKNOWN;
|
|
uint8_t presentVotes_ = 0;
|
|
uint8_t absentVotes_ = 0;
|
|
uint32_t lastPollMs_ = 0;
|
|
uint32_t lastFullScanMs_ = 0;
|
|
uint32_t logSeq_ = 0;
|
|
|
|
bool mountedEventPending_ = false;
|
|
bool removedEventPending_ = false;
|
|
};
|