Initial commit.

This commit is contained in:
conky
2026-08-31 15:45:58 +03:00
commit ec9805b01a
22 changed files with 1536 additions and 0 deletions

100
include/baro_channel.h Normal file
View File

@@ -0,0 +1,100 @@
#pragma once
#include <Arduino.h>
#include <math.h>
#include "config.h"
#include "ms5611_crc.h"
//
// One validated MS5611 measurement channel.
//
// The class owns everything that is identical for both sensors - reset and
// PROM/CRC handshake, per-poll validation, error accounting and the 1 second
// error LED pulse. Only the five driver calls at the bottom are virtual, and
// they are implemented once for the I2C part and once for the SPI part.
//
enum class BaroStatus : uint8_t
{
NotInitialised = 0,
Ok,
InitFailed, // reset/handshake did not complete
PromCrcError, // factory calibration failed its CRC-4 or is implausible
ReadError, // the driver reported a bus/ADC failure
OutOfRange, // values outside the MS5611 operating envelope
Stale, // sensor answers but has stopped producing new samples
};
// Short, log-friendly name for a status - never returns NULL.
const char *baroStatusName(BaroStatus status);
class BaroChannel
{
public:
BaroChannel(const char *name, uint8_t ledPin)
: _name(name), _ledPin(ledPin) {}
// Configures the LED pin and makes the first initialisation attempt.
void begin(uint32_t now);
// One acquisition cycle: read, validate, update status and LED.
// Blocks for roughly 2x the ADC conversion time of the configured OSR.
void poll(uint32_t now);
// Releases the error LED once its hold time has elapsed. Cheap, call often.
void updateLed(uint32_t now);
const char *name() const { return _name; }
BaroStatus status() const { return _status; }
bool isOk() const { return _status == BaroStatus::Ok; }
float pressure() const { return _pressure; } // mbar
float temperature() const { return _temperature; } // degrees C
uint32_t errorCount() const { return _errorCount; }
protected:
// Not deleted through this type - keeps the vtable free of a destructor
// slot and avoids dragging in operator delete.
~BaroChannel() = default;
// Reset the part and apply the configured oversampling.
virtual bool driverBegin() = 0;
// Fill prom[0..7] with the factory calibration words.
virtual void driverReadProm(uint16_t *prom) = 0;
// True when the driver reported MS5611_READ_OK.
virtual bool driverRead() = 0;
virtual float driverPressure() = 0;
virtual float driverTemperature() = 0;
private:
bool tryInit(uint32_t now);
void fail(BaroStatus status, uint32_t now);
const char *_name;
uint8_t _ledPin;
BaroStatus _status = BaroStatus::NotInitialised;
bool _initialised = false;
uint32_t _lastInitAttempt = 0;
float _pressure = NAN;
float _temperature = NAN;
uint8_t _repeatCount = 0;
uint8_t _errorStreak = 0;
uint32_t _errorCount = 0;
bool _ledOn = false;
uint32_t _ledOffAt = 0;
};
//
// The two concrete channels are built in their own translation units on
// purpose: MS5611.h and MS5611_SPI.h each define `enum osr_t` and their own
// MS5611_READ_OK, so including both in one file does not compile. These
// accessors hand out the instances without leaking either driver header.
//
BaroChannel &baroI2cChannel();
BaroChannel &baroSpiChannel();