Architecture¶
How the driver is put together: three layers, what each owns, and how one read reaches the sensor.
Figure description and sources
From top to bottom. Your application talks to one Mcp9700Thermistor
Drawn from: inc/mcp9700_thermistor.hpp Mcp9700Thermistor public calls; inc/mcp9700_thermistor.hpp AdcType contract; figure module docs/diagrams/figures/driver-layers.py.
The three layers¶
| Layer | What it is | Changes |
|---|---|---|
| Core | Mcp9700Thermistor<AdcType> |
Never, for a new board |
| Adapter contract | The AdcType parameter |
Never |
| Platform adapter | Your class, two methods | Once per MCU (Porting) |
The core is in inc/mcp9700_thermistor.hpp and
src/mcp9700_thermistor.ipp; the contract is documented on the class in the same
header. Everything above the adapter is the same on ESP32, STM32, a Linux host or the unit-test mock. That is how the
host tests run the real driver code without hardware.
How one read reaches the sensor¶
sequenceDiagram
participant A as Application
participant D as Mcp9700Thermistor
participant P as Your adapter
participant H as ADC and MCP9700
A->>D: ReadTemperatureCelsius(&t)
D->>D: initialised? output pointer not null?
D->>P: ReadChannelV(channel, &volts)
P->>H: one conversion on VOUT
H-->>P: raw code
P-->>D: 0 and volts (calibrated, at the pin)
D->>D: t = (volts − v_zero_c) / v_per_c
D-->>A: true (on a non-zero return: false, t unchanged)
Why a template parameter¶
The adapter is a class template parameter, not a virtual base class. The compiler sees your adapter's methods
directly and inlines them; the driver has no vtable, allocates nothing and needs no RTTI. There is no base class to
derive from either: any type with the two methods compiles, and a type without them fails to compile where the
driver calls them. The cost is that the driver type names the adapter: Mcp9700Thermistor<MyAdc>.
What the driver owns and what it does not¶
| The driver | Your adapter or application |
|---|---|
| The transfer function and its two coefficients | ADC set-up, channel mapping, calibration, dividers |
| The initialised state, the argument checks and the plausibility range check | Averaging, filtering, application limits |
Returning false on any failure |
Deciding what a failure means for your system |
The driver holds a non-owning pointer to your adapter: the adapter must outlive it. The object cannot be copied.
The constructor never touches the ADC; Initialize() does, through EnsureInitialized().
Source map¶
| Path | Contents |
|---|---|
inc/mcp9700_thermistor.hpp |
Mcp9700Thermistor<AdcType>, the default coefficients, GetMcp9700DriverVersion() |
src/mcp9700_thermistor.ipp |
Template implementation, included by the header |
inc/mcp9700_version.h.in |
Version header template, filled in by CMake |
cmake/hf_mcp9700_build_settings.cmake |
Version, include directories, ESP-IDF requirements |
tests/ |
Host unit tests and the compiled documentation snippets |
examples/esp32/ |
ESP-IDF application for the ESP32-C6 |