Skip to content

Commit

Permalink
WIP: make gpio signals regular types instead of templates
Browse files Browse the repository at this point in the history
Avoids the template template parameter in the driver connect()
implementations.
Proof-of-concept, STM32 only, only UART connect works for now.
  • Loading branch information
chris-durand committed Sep 18, 2021
1 parent 7e39919 commit 727fe18
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 27 deletions.
43 changes: 24 additions & 19 deletions src/modm/platform/gpio/stm32/connector.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@ namespace modm::platform
namespace detail
{

template< Peripheral peripheral, Gpio::Signal signal, template<Peripheral _> class... Signals >
template< Peripheral peripheral, Gpio::Signal signal, class... Signals >
struct GpioGetSignal;
template< Peripheral peripheral, Gpio::Signal signal, template<Peripheral _> class SignalT, template<Peripheral _> class... Signals >
template< Peripheral peripheral, Gpio::Signal signal, class SignalT, class... Signals >
struct GpioGetSignal<peripheral, signal, SignalT, Signals...>
{
using Data = typename SignalT::Data;
using Connection = typename Data::SignalConnection<SignalT, peripheral>;

using Gpio = std::conditional_t<
(SignalT<peripheral>::Signal == signal),
StaticGpio<typename SignalT<peripheral>::Data>,
(Connection::Signal == signal),
typename modm::platform::StaticGpio<Data>,
typename GpioGetSignal<peripheral, signal, Signals...>::Gpio
>;
};
Expand All @@ -43,12 +46,12 @@ struct GpioGetSignal<peripheral, signal>

} // namespace detail

template< Peripheral peripheral, template<Peripheral _> class... Signals >
template< Peripheral peripheral, class... Signals >
struct GpioConnector
{
template< class GpioQuery >
static constexpr bool Contains = (
std::is_same_v<typename Signals<peripheral>::Data, typename GpioQuery::Data> or ...);
std::is_same_v<typename Signals::Data::SignalConnection<Signals, peripheral>::Data, typename GpioQuery::Data> or ...);

template< class GpioQuery >
static constexpr bool IsValid = not std::is_same_v<typename GpioQuery::Type, GpioUnused>;
Expand All @@ -57,16 +60,17 @@ struct GpioConnector
using GetSignal = typename detail::GpioGetSignal<peripheral, signal, Signals...>::Gpio;

%% if target.family not in ["f1", "l1"]
template< template<Peripheral _> class Signal >
template< class Signal >
static void connectSignal()
{
using Pin = StaticGpio<typename Signal<peripheral>::Data>;
if constexpr(Signal<peripheral>::af == -2) {
using Connection = typename Signal::Data::SignalConnection<Signal, peripheral>;
using Pin = StaticGpio<typename Connection::Data>;
if constexpr(Connection::af == -2) {
Pin::disconnect();
Pin::setAnalogInput();
}
if constexpr (Signal<peripheral>::af >= 0) {
Pin::setAlternateFunction(Signal<peripheral>::af);
if constexpr (Connection::af >= 0) {
Pin::setAlternateFunction(Connection::af);
}
}

Expand All @@ -80,32 +84,33 @@ struct GpioConnector

static inline void disconnect()
{
(StaticGpio<typename Signals<peripheral>::Data>::disconnect(), ...);
(StaticGpio<typename Signals::Data::SignalConnection<Signals, peripheral>::Data>::disconnect(), ...);
}
};

%% if target.family in ["f1"]
%% for remap in remaps
%% set reg = "MAPR" if (remap["position"] | int) < 32 else "MAPR2"
%% set per = remap | formatPeripheral
template< template<Peripheral _> class... Signals >
template< class... Signals >
struct GpioConnector<Peripheral::{{per}}, Signals...>
{
template< class GpioQuery >
static constexpr bool Contains = (
std::is_same_v<typename Signals<Peripheral::{{per}}>::Data, typename GpioQuery::Data> or ...);
std::is_same_v<typename Signals::Data::SignalConnection<Signals, Peripheral::{{per}}>::Data, typename GpioQuery::Data> or ...);

template< class GpioQuery >
static constexpr bool IsValid = not std::is_same_v<typename GpioQuery::Type, GpioUnused>;

template< Gpio::Signal signal >
using GetSignal = typename detail::GpioGetSignal<Peripheral::{{per}}, signal, Signals...>::Gpio;

template< template<Peripheral _> class Signal >
template< class Signal >
static void connectSignal()
{
using Pin = StaticGpio<typename Signal<Peripheral::{{per}}>::Data>;
if constexpr(Signal<Peripheral::{{per}}>::af == -2) {
using Connection = typename Signal::Data::SignalConnection<Signal, Peripheral::{{per}}>;
using Pin = StaticGpio<typename Connection::Data>;
if constexpr(Connection::af == -2) {
Pin::setAnalogInput();
}
else {
Expand All @@ -116,7 +121,7 @@ struct GpioConnector<Peripheral::{{per}}, Signals...>
static inline void connect()
{
constexpr auto lmb = [](uint32_t id) { return 31 - std::countl_zero(id); };
static constexpr uint32_t id = (Signals<Peripheral::{{per}}>::Groups & ... & uint32_t(-1));
static constexpr uint32_t id = (Signals::Data::template SignalConnection<Signals, Peripheral::{{per}}>::Groups & ... & uint32_t(-1));
static_assert((id == uint32_t(-1)) or (lmb(id) == {{ remap.group | map(attribute="id") | join("ul) or (lmb(id) == ") }}ul),
"This pin set contains conflicting remap groups!\nAvailable groups for {{per}} are:\n"
%% for line in group_map | printSignalMap(per)
Expand All @@ -131,7 +136,7 @@ struct GpioConnector<Peripheral::{{per}}, Signals...>

static inline void disconnect()
{
(StaticGpio<typename Signals<Peripheral::{{per}}>::Data>::disconnect(), ...);
(StaticGpio<typename Signals::Data::SignalConnection<Signals, Peripheral::{{per}}>::Data>::disconnect(), ...);
}
};
%% endfor
Expand Down
24 changes: 17 additions & 7 deletions src/modm/platform/gpio/stm32/gpio_data.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,28 @@ struct Data{{ port ~ pin }} {
inline static void remap() { {{gpio.remap_reg}} {% if gpio.remap_value %}|= {% else %}&= ~{% endif %}{{gpio.remap_mask}}; }
%% endif

template<Peripheral p> struct BitBang { static_assert(
(p == Peripheral::BitBang), "Gpio{{ port ~ pin }}::BitBang only connects to software drivers!"); };

struct BitBang { using Data = Data{{ port ~ pin }}; };
%% for signal_name, signal_group in gpio.signals.items()
template<Peripheral p> struct {{ signal_name }} { static_assert(
(p == Peripheral::{{ signal_group | map(attribute="driver") | join(") or (p == Peripheral::") }}),{% if signal_group | length > 1 %}
{% endif %}"Gpio{{ port ~ pin }}::{{ signal_name }} only connects to {{ signal_group | map(attribute="driver") | join(" or ") }}!"); };
struct {{ signal_name }} { using Data = Data{{ port ~ pin }}; };
%% endfor

template<Peripheral p> static constexpr int8_t AdcChannel = -1;
template<Peripheral p> static constexpr int8_t DacChannel = -1;
template<typename Signal, Peripheral p> struct SignalConnection;
};
template<> struct Data{{ port ~ pin }}::BitBang<Peripheral::BitBang> {
template<Peripheral p> struct Data{{ port ~ pin }}::SignalConnection<Data{{ port ~ pin }}::BitBang, p> {
static_assert(
(p == Peripheral::BitBang), "Gpio{{ port ~ pin }}::BitBang only connects to software drivers!"); };
%% for signal_name, signal_group in gpio.signals.items()
template<Peripheral p> struct Data{{ port ~ pin }}::SignalConnection<Data{{ port ~ pin }}::{{ signal_name }}, p> {
static_assert(
(p == Peripheral::{{ signal_group | map(attribute="driver") | join(") or (p == Peripheral::") }}),{% if signal_group | length > 1 %}
{% endif %}"Gpio{{ port ~ pin }}::{{ signal_name }} only connects to {{ signal_group | map(attribute="driver") | join(" or ") }}!"); };
%% endfor


template<> struct Data{{ port ~ pin }}::SignalConnection<Data{{ port ~ pin }}::BitBang, Peripheral::BitBang> {
using Data = Data{{ port ~ pin }}; static constexpr int8_t af = -1;
static constexpr Gpio::Signal Signal = Gpio::Signal::BitBang;
%% if target.family in ["f1"]
Expand All @@ -50,7 +60,7 @@ template<> struct Data{{ port ~ pin }}::BitBang<Peripheral::BitBang> {
};
%% for signal_group in gpio.signals.values()
%% for signal in signal_group
template<> struct Data{{ port ~ pin }}::{{ signal.name }}<Peripheral::{{ signal.driver }}> {
template<> struct Data{{ port ~ pin }}::SignalConnection<Data{{ port ~ pin }}::{{ signal.name }}, Peripheral::{{ signal.driver }}> {
using Data = Data{{ port ~ pin }}; static constexpr int8_t af = {{ signal.af[0] if signal.af | length else (-2 if (signal.driver.startswith("Adc") or signal.driver.startswith("Dac") or signal.driver.startswith("Comp")) else -1) }};
static constexpr Gpio::Signal Signal = Gpio::Signal::{{ signal.name }};
%% if target.family in ["f1"]
Expand Down
2 changes: 1 addition & 1 deletion src/modm/platform/uart/stm32/uart.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public:
static constexpr size_t TxBufferSize = {{ options["buffer.tx"] }};

public:
template< template<Peripheral _> class... Signals >
template< class... Signals >
static void
connect(Gpio::InputType InputTypeRx = Gpio::InputType::PullUp,
Gpio::OutputType OutputTypeTx = Gpio::OutputType::PushPull)
Expand Down

0 comments on commit 727fe18

Please sign in to comment.