GCC Code Coverage Report


Directory: lib/fprime-samd/fprime-samd/Drv/AdcDriver/
File: AdcDriverHardwareStub.cpp
Date: 2026-09-26 00:05:12
Exec Total Coverage
Lines: 53 53 100.0%
Functions: 14 14 100.0%
Branches: 2 4 50.0%

Line Branch Exec Source
1 // ======================================================================
2 // \title AdcDriverHardwareStub.cpp
3 // \author crsmith
4 // \brief Stub hardware implementation for the ADC peripheral (Linux/test builds)
5 //
6 // This file is compiled for Linux/test builds to enable unit testing.
7 // For SAMD21 target builds, AdcDriverHardware.cpp would be used instead.
8 //
9 // The stub records the arguments of each hardware call and exposes injectable
10 // hardware state so unit tests can drive the component's logic without any real MCU.
11 // ======================================================================
12
13 #include "fprime-samd/Drv/AdcDriver/AdcDriverHardware.hpp"
14
15 namespace Samd21 {
16 namespace AdcHardware {
17
18 static StubState s_state = {};
19
20 132 StubState& getStubState() {
21 132 return s_state;
22 }
23
24 63 void resetStubState() {
25 63 s_state = StubState{};
26 63 }
27
28 37 void AdcHal::waitForGclkSync() {
29 37 s_state.waitForGclkSync_calls++;
30 // Stub never blocks - assumes hardware sync completes immediately
31 37 }
32
33 148 void AdcHal::waitForAdcSync() {
34 148 s_state.waitForAdcSync_calls++;
35 // Stub never blocks - assumes hardware sync completes immediately
36 148 }
37
38 37 void AdcHal::configure(AdcDriver::VoltageReference ref,
39 AdcDriver::Resolution res,
40 AdcDriver::SampleCount samples,
41 U8 samplingTime,
42 AdcDriver::Gain gain) {
43 // Call sync waits to track them (mirroring the real hardware sequence)
44 37 waitForGclkSync(); // Called once for GCLK setup
45 37 waitForAdcSync(); // Called for reset
46 37 waitForAdcSync(); // Called for REFCTRL
47 37 waitForAdcSync(); // Called for CTRLB
48 37 waitForAdcSync(); // Called for INPUTCTRL before dummy conversion
49 // Additional waits happen in the real implementation
50
51 37 s_state.configured = true;
52 37 s_state.configure_count++;
53 37 s_state.ref = ref;
54 37 s_state.res = res;
55 37 s_state.samples = samples;
56 37 s_state.samplingTime = samplingTime;
57 37 s_state.gain = gain;
58 37 }
59
60 2 void AdcHal::configureChannel(AdcDriver::AdcChannel channel) {
61 2 s_state.configureChannel_count++;
62 2 s_state.last_configured_channel = channel;
63 2 }
64
65 24 void AdcHal::selectChannel(AdcDriver::AdcChannel channel, U8 gain) {
66 24 s_state.selectChannel_count++;
67 24 s_state.selected_channel = channel;
68 24 s_state.selected_gain = gain;
69 24 }
70
71 24 void AdcHal::startConversion() {
72 24 s_state.startConversion_count++;
73 24 }
74
75 26 U32 AdcHal::readResult() {
76 // Model the auto-clear behavior: reading result clears RESRDY flag
77 // per SAMD21 datasheet ยง33.6.5
78 26 U32 value = s_state.result;
79 26 s_state.result_ready = false;
80 26 return value;
81 }
82
83 27 bool AdcHal::isResultReady() {
84
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 return s_state.result_ready;
85 }
86
87 27 bool AdcHal::isOverrun() {
88
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 return s_state.overrun;
89 }
90
91 3 void AdcHal::clearOverrun() {
92 3 s_state.clearOverrun_count++;
93 // Model the write-1-clear: once cleared, no longer set
94 3 s_state.overrun = false;
95 3 }
96
97 37 void AdcHal::enableInterrupt() {
98 // Stub no-op: interrupt enable recorded implicitly
99 37 }
100
101 37 void AdcHal::enableAdcInterrupts() {
102 // Stub no-op: peripheral interrupt enable recorded implicitly
103 37 }
104
105 } // namespace AdcHardware
106 } // namespace Samd21
107