had OLED sleep ability and better SD card mount monitoring and ring buffer for error messages

This commit is contained in:
John Poole 2026-04-07 20:48:12 -07:00
commit 15a5dbe006
8 changed files with 223 additions and 40 deletions

View file

@ -46,6 +46,10 @@
#define FW_BUILD_UTC unknown
#endif
#ifndef LOG_AP_IP_OCTET
#define LOG_AP_IP_OCTET 23
#endif
#define FIELD_QA_STR_INNER(x) #x
#define FIELD_QA_STR(x) FIELD_QA_STR_INNER(x)
@ -59,7 +63,7 @@ static constexpr const char* kStorageName = "SD";
static constexpr const char* kLogDir = "/logs";
static constexpr const char* kLogApPrefix = "GPSQA-";
static constexpr const char* kLogApPassword = "";
static constexpr uint8_t kLogApIpOctet = 23;
static constexpr uint8_t kLogApIpOctet = LOG_AP_IP_OCTET;
static constexpr uint32_t kSerialDelayMs = 4000;
static constexpr uint32_t kSamplePeriodMs = 1000;
static constexpr uint32_t kLogFlushPeriodMs = 10000;

View file

@ -21,6 +21,8 @@ void DisplayManager::begin() {
Wire.begin(OLED_SDA, OLED_SCL);
m_oled.setI2CAddress(OLED_ADDR << 1);
m_oled.begin();
m_oled.setPowerSave(0);
m_powerSave = false;
}
void DisplayManager::drawLines(const char* l1,
@ -40,15 +42,24 @@ void DisplayManager::drawLines(const char* l1,
m_oled.sendBuffer();
}
void DisplayManager::showBoot(const char* line2, const char* line3) {
drawLines(kExerciseName, kFirmwareVersion, line2, line3);
void DisplayManager::showBoot(const char* line2, const char* line3, const char* line4, const char* batteryText) {
char header[24];
if (batteryText && batteryText[0] != '\0') {
snprintf(header, sizeof(header), "%s %s", kExerciseName, batteryText);
drawLines(header, kFirmwareVersion, line2, line3, line4);
} else {
drawLines(kExerciseName, kFirmwareVersion, line2, line3, line4);
}
}
void DisplayManager::showError(const char* line1, const char* line2) {
drawLines(kExerciseName, "ERROR", line1, line2);
}
void DisplayManager::showSample(const GnssSample& sample, const RunStats& stats, bool recording) {
void DisplayManager::showSample(const GnssSample& sample,
const RunStats& stats,
bool recording,
const char* batteryText) {
char l1[24];
char l2[20];
char l3[20];
@ -56,7 +67,11 @@ void DisplayManager::showSample(const GnssSample& sample, const RunStats& stats,
char l5[20];
char l6[20];
snprintf(l1, sizeof(l1), "%s", recording ? "*RECORDING" : "Halted");
snprintf(l1,
sizeof(l1),
"%s %s",
recording ? "*RECORDING" : "Halted",
(batteryText && batteryText[0] != '\0') ? batteryText : "--.-v");
snprintf(l2, sizeof(l2), "FIX: %s", fixTypeToString(sample.fixType));
snprintf(l3, sizeof(l3), "USED: %d/%d", sample.satsUsed < 0 ? 0 : sample.satsUsed, sample.satsInView < 0 ? 0 : sample.satsInView);
if (sample.validHdop) {
@ -69,4 +84,16 @@ void DisplayManager::showSample(const GnssSample& sample, const RunStats& stats,
drawLines(l1, l2, l3, l4, l5, l6);
}
void DisplayManager::setPowerSave(bool enabled) {
if (m_powerSave == enabled) {
return;
}
m_oled.setPowerSave(enabled ? 1 : 0);
m_powerSave = enabled;
}
bool DisplayManager::powerSave() const {
return m_powerSave;
}
} // namespace field_qa

View file

@ -10,9 +10,14 @@ namespace field_qa {
class DisplayManager {
public:
void begin();
void showBoot(const char* line2, const char* line3 = nullptr);
void showBoot(const char* line2,
const char* line3 = nullptr,
const char* line4 = nullptr,
const char* batteryText = nullptr);
void showError(const char* line1, const char* line2 = nullptr);
void showSample(const GnssSample& sample, const RunStats& stats, bool recording);
void showSample(const GnssSample& sample, const RunStats& stats, bool recording, const char* batteryText);
void setPowerSave(bool enabled);
bool powerSave() const;
private:
void drawLines(const char* l1,
@ -23,6 +28,7 @@ class DisplayManager {
const char* l6 = nullptr);
U8G2_SH1106_128X64_NONAME_F_HW_I2C m_oled{U8G2_R0, U8X8_PIN_NONE};
bool m_powerSave = false;
};
} // namespace field_qa

View file

@ -265,13 +265,14 @@ bool StorageManager::appendLine(const String& line) {
return appendBytes(record.c_str(), record.length());
}
void StorageManager::appendSampleCsv(const GnssSample& sample,
bool StorageManager::appendSampleCsv(const GnssSample& sample,
uint32_t sampleSeq,
uint32_t msSinceRunStart,
const char* runId,
const char* bootTimestampUtc) {
if (!m_file) {
return;
m_lastError = "log file not open";
return false;
}
if (m_file.size() == 0) {
writeHeader(runId, bootTimestampUtc);
@ -350,10 +351,10 @@ void StorageManager::appendSampleCsv(const GnssSample& sample,
line += kLogFieldDelimiter;
line += String(sample.longestNoFixMs);
line += ",,,,,,,";
(void)appendLine(line);
return appendLine(line);
}
void StorageManager::appendSatelliteCsv(const GnssSample& sample,
bool StorageManager::appendSatelliteCsv(const GnssSample& sample,
uint32_t sampleSeq,
uint32_t msSinceRunStart,
const SatelliteInfo* satellites,
@ -361,7 +362,10 @@ void StorageManager::appendSatelliteCsv(const GnssSample& sample,
const char* runId,
const char* bootTimestampUtc) {
if (!satellites || satelliteCount == 0 || !m_file) {
return;
if (!m_file) {
m_lastError = "log file not open";
}
return false;
}
if (m_file.size() == 0) {
writeHeader(runId, bootTimestampUtc);
@ -458,26 +462,30 @@ void StorageManager::appendSatelliteCsv(const GnssSample& sample,
line += String(sat.snr);
line += kLogFieldDelimiter;
line += sat.usedInSolution ? "1" : "0";
(void)appendLine(line);
if (!appendLine(line)) {
return false;
}
}
return true;
}
void StorageManager::flush() {
bool StorageManager::flush() {
if (!m_file) {
return;
return false;
}
if (m_bufferLengths[m_activeBuffer] > 0) {
m_bufferPending[m_activeBuffer] = true;
}
if (!writePendingBuffer()) {
return;
return false;
}
m_file.flush();
return true;
}
void StorageManager::close() {
flush();
(void)flush();
if (m_file) {
m_file.close();
}

View file

@ -17,19 +17,19 @@ class StorageManager {
bool fileOpen() const;
size_t bufferedBytes() const;
size_t logFileCount() const;
void appendSampleCsv(const GnssSample& sample,
bool appendSampleCsv(const GnssSample& sample,
uint32_t sampleSeq,
uint32_t msSinceRunStart,
const char* runId,
const char* bootTimestampUtc);
void appendSatelliteCsv(const GnssSample& sample,
bool appendSatelliteCsv(const GnssSample& sample,
uint32_t sampleSeq,
uint32_t msSinceRunStart,
const SatelliteInfo* satellites,
size_t satelliteCount,
const char* runId,
const char* bootTimestampUtc);
void flush();
bool flush();
void close();
void listFiles(Stream& out);
void catFile(Stream& out, const char* path);