-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
171 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
--- | ||
tags: | ||
- Affine Space | ||
- Embedded | ||
- Text Formatting | ||
--- | ||
|
||
# `hw_voltage` | ||
|
||
!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/jjod7hvsd)" | ||
|
||
As it was stated in [The Affine Space](../framework_basics/the_affine_space.md) chapter, | ||
every measurement can (and probably should) be modelled as a `quantity_point`. This is | ||
a perfect example of such a use case. | ||
|
||
This example implements a simplified scenario of measuring voltage read from hardware through | ||
a mapped 16-bits register. The actual voltage range of [-10 V, 10 V] is mapped to [-32767, 32767] | ||
on hardware. Translation of the value requires not only scaling of the value but also applying | ||
of an offset. | ||
|
||
First we include all the dependencies: | ||
|
||
```cpp title="hw_voltage.cpp" linenums="1" | ||
--8<-- "example/hw_voltage.cpp:28:43" | ||
``` | ||
|
||
Next, we specify the real measurement voltage range to be in the range of [-10, 10]: | ||
|
||
```cpp title="hw_voltage.cpp" linenums="17" | ||
--8<-- "example/hw_voltage.cpp:45:48" | ||
``` | ||
|
||
and provide a storage type and special values for the hardware representation: | ||
|
||
```cpp title="hw_voltage.cpp" linenums="21" | ||
--8<-- "example/hw_voltage.cpp:50:56" | ||
``` | ||
|
||
Finally, we define a quantity point origin, an offset unit that scales the value and uses this | ||
origin to offset the zero of the sale, and a dedicated quantity point alias using those: | ||
|
||
```cpp title="hw_voltage.cpp" linenums="28" | ||
--8<-- "example/hw_voltage.cpp:60:66" | ||
``` | ||
|
||
Now, when everything is ready, we can simulate mapping of our hardware register, and provide | ||
a helper function that will read the value and construct a quantity point from the obtained copy: | ||
|
||
```cpp title="hw_voltage.cpp" linenums="35" | ||
--8<-- "example/hw_voltage.cpp:69:77" | ||
``` | ||
|
||
We also provide a simple print helper for our quantity points: | ||
|
||
```cpp title="hw_voltage.cpp" linenums="44" | ||
--8<-- "example/hw_voltage.cpp:79:82" | ||
``` | ||
|
||
In the main function we simulate setting of 3 values by our hardware. Each of them is read | ||
and printed in the voltage unit used on the hardware as well as in the standard SI unit: | ||
|
||
```cpp title="hw_voltage.cpp" linenums="48" | ||
--8<-- "example/hw_voltage.cpp:84:" | ||
``` | ||
|
||
The above program results with the following text output: | ||
|
||
```text | ||
0 hwV (-10 V) | ||
32767 hwV ( 0 V) | ||
65534 hwV ( 10 V) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// The MIT License (MIT) | ||
// | ||
// Copyright (c) 2018 Mateusz Pusz | ||
// | ||
// Permission is hereby granted, free of charge, to any person obtaining a copy | ||
// of this software and associated documentation files (the "Software"), to deal | ||
// in the Software without restriction, including without limitation the rights | ||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
// copies of the Software, and to permit persons to whom the Software is | ||
// furnished to do so, subject to the following conditions: | ||
// | ||
// The above copyright notice and this permission notice shall be included in all | ||
// copies or substantial portions of the Software. | ||
// | ||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
// SOFTWARE. | ||
|
||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
// !!! Before you commit any changes to this file please make sure to check if it !!! | ||
// !!! renders correctly in the documentation "Examples" section. !!! | ||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
|
||
#include <mp-units/compat_macros.h> | ||
#ifdef MP_UNITS_IMPORT_STD | ||
import std; | ||
#else | ||
#include <optional> | ||
#include <print> | ||
#endif | ||
#ifdef MP_UNITS_MODULES | ||
import mp_units; | ||
#else | ||
#include <mp-units/format.h> | ||
#include <mp-units/systems/isq.h> | ||
#include <mp-units/systems/si.h> | ||
#endif | ||
|
||
using namespace mp_units; | ||
|
||
// real voltage range | ||
inline constexpr int min_voltage = -10; | ||
inline constexpr int max_voltage = 10; | ||
inline constexpr int voltage_range = max_voltage - min_voltage; | ||
|
||
// hardware encoding of voltage | ||
using voltage_hw_t = std::uint16_t; | ||
inline constexpr voltage_hw_t voltage_hw_error = std::numeric_limits<voltage_hw_t>::max(); | ||
inline constexpr voltage_hw_t voltage_hw_min = 0; | ||
inline constexpr voltage_hw_t voltage_hw_max = voltage_hw_error - 1; | ||
inline constexpr voltage_hw_t voltage_hw_range = voltage_hw_max - voltage_hw_min; | ||
inline constexpr voltage_hw_t voltage_hw_zero = voltage_hw_range / 2; | ||
|
||
|
||
// clang-format off | ||
inline constexpr struct hw_voltage_origin final : | ||
relative_point_origin<absolute<si::volt>(min_voltage)> {} hw_voltage_origin; | ||
|
||
inline constexpr struct hw_voltage_unit final : | ||
named_unit<"hwV", mag_ratio<voltage_range, voltage_hw_range> * si::volt, hw_voltage_origin> {} hw_voltage_unit; | ||
|
||
using hw_voltage_quantity_point = quantity_point<hw_voltage_unit, hw_voltage_origin, voltage_hw_t>; | ||
// clang-format on | ||
|
||
// mapped HW register | ||
volatile voltage_hw_t hw_voltage_value; | ||
|
||
std::optional<hw_voltage_quantity_point> read_hw_voltage() | ||
{ | ||
voltage_hw_t local_copy = hw_voltage_value; | ||
if (local_copy == voltage_hw_error) return std::nullopt; | ||
return absolute<hw_voltage_unit>(local_copy); | ||
} | ||
|
||
void print(QuantityPoint auto qp) | ||
{ | ||
std::println("{:10} ({:5})", qp.quantity_from_zero(), value_cast<double, si::volt>(qp).quantity_from_zero()); | ||
} | ||
|
||
int main() | ||
{ | ||
// simulate reading of 3 values from the hardware | ||
hw_voltage_value = voltage_hw_min; | ||
quantity_point qp1 = read_hw_voltage().value(); | ||
hw_voltage_value = voltage_hw_zero; | ||
quantity_point qp2 = read_hw_voltage().value(); | ||
hw_voltage_value = voltage_hw_max; | ||
quantity_point qp3 = read_hw_voltage().value(); | ||
|
||
print(qp1); | ||
print(qp2); | ||
print(qp3); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters