|
1 | 1 | /////////////////////////////////////////////////////////////////////////////// |
2 | | -// Copyright Christopher Kormanyos 2018 - 2023. |
| 2 | +// Copyright Christopher Kormanyos 2018 - 2025. |
3 | 3 | // Distributed under the Boost Software License, |
4 | 4 | // Version 1.0. (See accompanying file LICENSE_1_0.txt |
5 | 5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | 6 | // |
7 | 7 |
|
8 | 8 | // chapter04_01-001_led_hierarchy.cpp |
9 | | -// See also https://godbolt.org/z/7MzKGEevh |
| 9 | +// See also https://godbolt.org/z/b4e5E1M8q |
10 | 10 |
|
11 | 11 | #include <algorithm> |
12 | 12 | #include <cstdint> |
13 | | -#include <iostream> |
14 | 13 |
|
15 | 14 | class led_base |
16 | 15 | { |
17 | 16 | public: |
18 | | - virtual void toggle() = 0; // Pure abstract. |
19 | | - virtual ~led_base() = default; // Virtual destructor. |
| 17 | + // Virtual default destructor. |
| 18 | + virtual ~led_base() = default; |
| 19 | + |
| 20 | + // Pure virtual. |
| 21 | + virtual auto toggle() noexcept -> void = 0; |
20 | 22 |
|
21 | 23 | // Interface for querying the LED state. |
22 | | - constexpr auto state_is_on() const noexcept -> bool { return is_on; } |
| 24 | + auto state_is_on() const noexcept |
| 25 | + -> bool { return is_on; } |
23 | 26 |
|
24 | | - // Non-implemented (deleted) copy constructors. |
25 | | - led_base(const led_base&) = delete; |
26 | | - led_base(led_base&&) noexcept = delete; |
| 27 | +protected: |
| 28 | + // A protected default constructor. |
| 29 | + led_base() = default; |
27 | 30 |
|
28 | | - // Non-implemented (deleted) assignment operators. |
29 | | - constexpr auto operator=(const led_base&) -> led_base& = delete; |
30 | | - constexpr auto operator=(led_base&&) noexcept -> led_base& = delete; |
| 31 | + auto set_is_on(const bool val) noexcept |
| 32 | + -> void { is_on = val; } |
31 | 33 |
|
32 | | -protected: |
| 34 | +private: |
33 | 35 | bool is_on { }; |
34 | 36 |
|
35 | | - // A protected default constructor. |
36 | | - constexpr led_base() = default; |
| 37 | + // Private non-implemented copy constructor. |
| 38 | + led_base(const led_base&) = delete; |
| 39 | + |
| 40 | + // Private non-implemented assignment operator. |
| 41 | + auto operator=(const led_base&) |
| 42 | + -> const led_base& = delete; |
37 | 43 | }; |
38 | 44 |
|
39 | 45 | class led_port : public led_base |
40 | 46 | { |
41 | 47 | public: |
42 | | - using port_type = std::uint8_t; |
43 | | - using bval_type = std::uint8_t; |
| 48 | + using port_type = std::uintptr_t; |
| 49 | + using bval_type = std::uintptr_t; |
44 | 50 |
|
45 | | - explicit constexpr led_port(const port_type p, |
46 | | - const bval_type b = static_cast<bval_type>(UINT8_C(0))) |
47 | | - : port(p), |
48 | | - bval(b) { static_cast<void>(bval); } |
| 51 | + explicit led_port(const port_type p, |
| 52 | + const bval_type b) : port(p), |
| 53 | + bval(b) |
| 54 | + { |
| 55 | + // ... |
| 56 | + } |
49 | 57 |
|
50 | 58 | ~led_port() override = default; |
51 | 59 |
|
52 | | - auto toggle() -> void override |
| 60 | + auto toggle() noexcept -> void override |
53 | 61 | { |
54 | | - // Toggle the is_on indication flag. |
55 | | - is_on = (!is_on); |
| 62 | + // Toggle the LED. |
| 63 | + *reinterpret_cast<volatile bval_type*>(port) |
| 64 | + ^= bval; |
56 | 65 |
|
57 | | - // Show the PC simulated port LED. |
58 | | - std::cout << "LED port(" << std::showbase << std::hex << unsigned(port) << "): "; |
| 66 | + // Toggle the is_on indication flag. |
| 67 | + const bool val_on |
| 68 | + { (!led_base::state_is_on()) }; |
59 | 69 |
|
60 | | - std::cout << (is_on ? "is on" : "is off") << std::endl; |
| 70 | + led_base::set_is_on(val_on); |
61 | 71 | } |
62 | 72 |
|
63 | 73 | private: |
@@ -101,52 +111,53 @@ class led_pwm : public led_base |
101 | 111 |
|
102 | 112 | ~led_pwm() override = default; |
103 | 113 |
|
104 | | - auto toggle() -> void override |
| 114 | + auto toggle() noexcept -> void override |
105 | 115 | { |
106 | 116 | // Toggle the duty cycle. |
107 | | - const auto duty = |
108 | | - static_cast<std::uint8_t> |
109 | | - ( |
110 | | - (my_pwm->get_duty() > static_cast<std::uint8_t>(UINT8_C(0))) |
111 | | - ? static_cast<std::uint8_t>(UINT8_C(0)) |
112 | | - : static_cast<std::uint8_t>(UINT8_C(100)) |
113 | | - ); |
114 | | - |
115 | | - my_pwm->set_duty(duty); |
| 117 | + const std::uint8_t duty = |
| 118 | + (my_pwm->get_duty() > 0U) ? 0U : 100U; |
116 | 119 |
|
117 | 120 | // Toggle the LED with the PWM signal. |
118 | | - is_on = (my_pwm->get_duty() > static_cast<std::uint8_t>(UINT8_C(0))); |
| 121 | + my_pwm->set_duty(duty); |
119 | 122 |
|
120 | | - // Show the PC simulated pwm LED. |
121 | | - std::cout << "LED pwm(" << std::dec << static_cast<unsigned>(my_pwm->get_channel()) << "): "; |
| 123 | + const bool val_on { (duty != 0U) }; |
122 | 124 |
|
123 | | - std::cout << (is_on ? "is on" : "is off") << std::endl; |
| 125 | + led_base::set_is_on(val_on); |
124 | 126 | } |
125 | 127 |
|
126 | 128 | // This LED class also supports dimming. |
127 | 129 | auto dimming(const std::uint8_t duty) -> void |
128 | 130 | { |
129 | 131 | my_pwm->set_duty(duty); |
130 | | - |
131 | | - is_on = (duty != static_cast<std::uint8_t>(UINT8_C(0))); |
| 132 | + led_base::set_is_on(duty != 0U); |
132 | 133 | } |
133 | 134 |
|
134 | 135 | private: |
135 | | - pwm* my_pwm { nullptr }; |
| 136 | + pwm* my_pwm { }; |
136 | 137 | }; |
137 | 138 |
|
| 139 | +namespace mcal |
| 140 | +{ |
| 141 | + namespace reg |
| 142 | + { |
| 143 | + // Simulate the transmit and receive hardware buffers on the PC. |
| 144 | + std::uint8_t dummy_register_port0 { }; |
| 145 | + std::uint8_t dummy_register_port1 { }; |
| 146 | + } |
| 147 | +} |
| 148 | + |
138 | 149 | namespace |
139 | 150 | { |
140 | 151 | // Two simulated port LEDs. |
141 | 152 | led_port led0 |
142 | 153 | { |
143 | | - static_cast<led_port::port_type>(UINT8_C(0x12)), |
| 154 | + reinterpret_cast<led_port::port_type>(&mcal::reg::dummy_register_port0), |
144 | 155 | static_cast<led_port::bval_type>(UINT8_C(1)) |
145 | 156 | }; |
146 | 157 |
|
147 | 158 | led_port led1 |
148 | 159 | { |
149 | | - static_cast<led_port::port_type>(UINT8_C(0x34)), |
| 160 | + reinterpret_cast<led_port::port_type>(&mcal::reg::dummy_register_port1), |
150 | 161 | static_cast<led_port::bval_type>(UINT8_C(2)) |
151 | 162 | }; |
152 | 163 |
|
|
0 commit comments