• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 #include "pw_analog/analog_input.h"
16 #include "pw_chrono/system_clock.h"
17 #include "pw_result/result.h"
18 #include "pw_status/try.h"
19 
20 namespace pw::analog {
21 
22 // The common interface for obtaining voltage samples in microvolts. This
23 // interface represents a single voltage input or channel. Users will need to
24 // supply their own ADC driver implementation in order to configure and enable
25 // the ADC peripheral in order to provide the reference voltages and to
26 // configure and enable the ADC peripheral where needed. Users are responsible
27 // for managing multithreaded access to the ADC driver if the ADC services
28 // multiple channels.
29 class MicrovoltInput : public AnalogInput {
30  public:
31   // Specifies the max and min microvolt range the analog input can measure.
32   // The reference voltage difference cannot be bigger than sizeof(int32_t)
33   // which should be just above 2000V.
34   // * These values do not change at run time.
35   // * Inversion of min/max is supported.
36   struct References {
37     int32_t max_voltage_uv;  // Microvolts at AnalogInput::Limits::max
38     int32_t min_voltage_uv;  // Microvolts at AnalogInput::Limits::min.
39   };
40 
41   virtual ~MicrovoltInput() = default;
42 
43   // Blocks until the specified timeout duration has elapsed or the voltage
44   // sample has been returned, whichever comes first.
45   //
46   // This method is thread safe.
47   //
48   // Returns:
49   //   Microvolts (uV).
50   //   ResourceExhuasted: ADC peripheral in use.
51   //   DeadlineExceedded: Timed out waiting for a sample.
52   //   Other statuses left up to the implementer.
TryReadMicrovoltsFor(chrono::SystemClock::duration timeout)53   Result<int32_t> TryReadMicrovoltsFor(chrono::SystemClock::duration timeout) {
54     return TryReadMicrovoltsUntil(
55         chrono::SystemClock::TimePointAfterAtLeast(timeout));
56   }
57 
58   // Blocks until the deadline time has been reached or the voltage sample has
59   // been returned, whichever comes first.
60   //
61   // This method is thread safe.
62   //
63   // Returns:
64   //   Microvolts (uV).
65   //   ResourceExhuasted: ADC peripheral in use.
66   //   DeadlineExceedded: Timed out waiting for a sample.
67   //   Other statuses left up to the implementer.
TryReadMicrovoltsUntil(chrono::SystemClock::time_point deadline)68   Result<int32_t> TryReadMicrovoltsUntil(
69       chrono::SystemClock::time_point deadline) {
70     PW_TRY_ASSIGN(const int32_t sample, TryReadUntil(deadline));
71 
72     const References reference = GetReferences();
73     const AnalogInput::Limits limits = GetLimits();
74 
75     constexpr int64_t kMaxReferenceDiffUv = std::numeric_limits<int32_t>::max();
76 
77     if (std::abs(static_cast<int64_t>(reference.max_voltage_uv) -
78                  static_cast<int64_t>(reference.min_voltage_uv)) >
79         kMaxReferenceDiffUv) {
80       return pw::Status::Internal();
81     }
82 
83     return (((static_cast<int64_t>(sample) - static_cast<int64_t>(limits.min)) *
84              (reference.max_voltage_uv - reference.min_voltage_uv)) /
85             (limits.max - limits.min)) +
86            reference.min_voltage_uv;
87   }
88 
89  private:
90   // Returns the reference voltage needed to calculate the voltage.
91   // These values do not change at run time.
92   virtual References GetReferences() const = 0;
93 };
94 
95 }  // namespace pw::analog
96