Skip to content

Commit bc5470f

Browse files
committed
[stm32] Add extended software gpio port with runtime single pin access
1 parent 801b8a1 commit bc5470f

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

src/modm/platform/gpio/stm32/module.lb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ def build(env):
305305
env.template("enable.cpp.in")
306306
env.template("gpio_accessor.hpp.in")
307307

308+
env.copy("random_access_port.hpp")
308309
env.copy("../common/inverted.hpp", "inverted.hpp")
309310
env.copy("../common/connector.hpp", "connector.hpp")
310311
env.template("../common/connector_detail.hpp.in", "connector_detail.hpp")
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/*
2+
* Copyright (c) 2021, Christopher Durand
3+
*
4+
* This file is part of the modm project.
5+
*
6+
* This Source Code Form is subject to the terms of the Mozilla Public
7+
* License, v. 2.0. If a copy of the MPL was not distributed with this
8+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
9+
*/
10+
// ----------------------------------------------------------------------------
11+
12+
#ifndef MODM_STM32_RANDOM_ACCESS_PORT_HPP
13+
#define MODM_STM32_RANDOM_ACCESS_PORT_HPP
14+
15+
#include <array>
16+
#include <iterator>
17+
#include <algorithm>
18+
19+
#include "software_port.hpp"
20+
#include "gpio_accessor.hpp"
21+
22+
namespace modm::platform
23+
{
24+
25+
/**
26+
* Extended software Gpio port with single pin random access. It inherits all
27+
* functionality from SoftwareGpioPort with the additional feature to set and
28+
* read single Gpios with a runtime index.
29+
*
30+
* It conforms to the std::ranges::random_access_range concept.
31+
*
32+
* Example:
33+
* @code
34+
* using Port = RandomAccessPort<GpioA1, GpioB4, GpioC8>;
35+
* Port::setOutput();
36+
* Port::set(2); // set pin with index 2 => A1
37+
*
38+
* Port port;
39+
* // set pin C8
40+
* GpioAccessor pin = port[0];
41+
* pin.set();
42+
*
43+
* auto reversedPins = port | std::views::reverse;
44+
* for(auto pin : reversedPins) {
45+
* pin.toggle();
46+
* }
47+
* @endcode
48+
*
49+
* @tparam Gpios Up to 32 Gpios, ordered MSB to LSB
50+
*
51+
* @author Christopher Durand
52+
* @ingroup modm_platform_gpio
53+
*/
54+
template<typename... Gpios>
55+
class RandomAccessPort : public SoftwareGpioPort<Gpios...>
56+
{
57+
public:
58+
using Index = int_fast8_t;
59+
static constexpr inline size_t Size{sizeof...(Gpios)};
60+
61+
private:
62+
static constexpr inline std::array<GpioAccessor, Size> GpioPins = [](){
63+
auto gpios = makeGpioArray<Gpios...>();
64+
// Reverse pin order to match SoftwareGpioPort indexing
65+
std::reverse(gpios.begin(), gpios.end());
66+
return gpios;
67+
}();
68+
69+
friend class GpioIterator;
70+
71+
public:
72+
class GpioIterator
73+
{
74+
private:
75+
Index index_;
76+
77+
public:
78+
using iterator_category = std::random_access_iterator_tag;
79+
using difference_type = Index;
80+
using value_type = GpioAccessor;
81+
using reference = const GpioAccessor&;
82+
83+
constexpr GpioIterator() = default;
84+
constexpr explicit GpioIterator(Index index) : index_{index}
85+
{}
86+
87+
constexpr inline GpioIterator&
88+
operator+=(difference_type diff) { index_ += diff; return *this; }
89+
90+
constexpr inline GpioIterator&
91+
operator-=(difference_type diff) { index_ -= diff; return *this; }
92+
93+
constexpr inline reference
94+
operator*() const { return RandomAccessPort::GpioPins[index_]; }
95+
96+
constexpr inline reference
97+
operator[](difference_type diff) const { return RandomAccessPort::GpioPins[index_ + diff]; }
98+
99+
constexpr inline GpioIterator&
100+
operator++() { ++index_; return *this; }
101+
102+
constexpr inline GpioIterator&
103+
operator--() { --index_; return *this; }
104+
105+
constexpr inline GpioIterator
106+
operator++(int) { GpioIterator tmp{*this}; ++index_; return tmp; }
107+
108+
constexpr inline GpioIterator
109+
operator--(int) { GpioIterator tmp{*this}; --index_; return tmp; }
110+
111+
constexpr inline difference_type
112+
operator-(const GpioIterator& rhs) const { return index_ - rhs.index_; }
113+
114+
constexpr inline GpioIterator
115+
operator+(difference_type diff) const { return GpioIterator{index_ + diff}; }
116+
117+
constexpr inline GpioIterator
118+
operator-(difference_type diff) const { return GpioIterator{index_ - diff}; }
119+
120+
friend constexpr inline GpioIterator
121+
operator+(difference_type lhs, const GpioIterator& rhs) { return GpioIterator{lhs + rhs.index_}; }
122+
123+
friend constexpr inline GpioIterator
124+
operator-(difference_type lhs, const GpioIterator& rhs) { return GpioIterator{lhs - rhs.index_}; }
125+
126+
constexpr inline auto
127+
operator<=>(const GpioIterator& rhs) const = default;
128+
};
129+
static_assert(std::random_access_iterator<GpioIterator>);
130+
131+
constexpr GpioIterator
132+
begin() const { return GpioIterator{0}; }
133+
134+
constexpr GpioIterator
135+
end() const { return GpioIterator{Size}; }
136+
137+
constexpr const GpioAccessor&
138+
operator[](Index index) const
139+
{
140+
return GpioPins[index];
141+
}
142+
143+
static void set(Index index, bool enable)
144+
{
145+
GpioPins[index].set(enable);
146+
}
147+
148+
static void set(Index index)
149+
{
150+
GpioPins[index].set();
151+
}
152+
153+
static void reset(Index index)
154+
{
155+
GpioPins[index].reset();
156+
}
157+
158+
static void toggle(Index index)
159+
{
160+
GpioPins[index].toggle();
161+
}
162+
163+
static bool read(Index index)
164+
{
165+
return GpioPins[index].read();
166+
}
167+
168+
static bool isSet(Index index)
169+
{
170+
return GpioPins[index].isSet();
171+
}
172+
};
173+
174+
}
175+
176+
#endif // MODM_STM32_RANDOM_ACCESS_PORT_HPP

0 commit comments

Comments
 (0)