From 07715a71514fbc61b0447dc6c8c30ba385b79fef Mon Sep 17 00:00:00 2001 From: "Sascha Schade (strongly-typed)" Date: Tue, 27 Nov 2018 18:27:43 +0100 Subject: [PATCH] [arch] Add I2C multiplexer as I2C device --- .../architecture/interface/gpio_expander.hpp | 2 +- .../interface/i2c_multiplexer.hpp | 117 ++++++++++++++++++ src/modm/architecture/module.lb | 15 +++ 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 src/modm/architecture/interface/i2c_multiplexer.hpp diff --git a/src/modm/architecture/interface/gpio_expander.hpp b/src/modm/architecture/interface/gpio_expander.hpp index 8d0a36c2b7..cad784cbf7 100644 --- a/src/modm/architecture/interface/gpio_expander.hpp +++ b/src/modm/architecture/interface/gpio_expander.hpp @@ -141,7 +141,7 @@ class GpioExpander /// Returns the input bits: 0 for low, 1 for high Pins getInputs() const; -#endif +#endif // __DOXYGEN__ }; /** diff --git a/src/modm/architecture/interface/i2c_multiplexer.hpp b/src/modm/architecture/interface/i2c_multiplexer.hpp new file mode 100644 index 0000000000..52f9cc884c --- /dev/null +++ b/src/modm/architecture/interface/i2c_multiplexer.hpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2018, Sascha Schade + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#ifndef MODM_I2C_MULTIPLEXER_HPP +#define MODM_I2C_MULTIPLEXER_HPP + +#include + +namespace modm +{ + +/** + * Interface of an I2C Multiplexer. + * + * All I2C multiplexer driver should implement this interface. + * @ingroup modm_architecture_i2c_multiplexer + */ +template < + auto &multiplexer, + typename std::remove_reference_t::Channel channel > + class I2cMultiplexerChannel : public modm::I2cMaster +{ +public: + static constexpr auto &i2cMultiplexer = multiplexer; + +public: + static bool + start(I2cTransaction *transaction, ConfigurationHandler handler = nullptr); +}; + +/// @ingroup modm_architecture_i2c_multiplexer +struct i2cMultiplexer +{ +public: + enum class + Channel : uint8_t + { + Ch0 = 0, + Ch1 = 1, + Ch2 = 2, + Ch3 = 3, + Ch4 = 4, + Ch5 = 5, + Ch6 = 6, + Ch7 = 7 + }; +}; // struct i2cMultiplexer + + +/// @ingroup modm_architecture_i2c_multiplexer +template < class I2cMaster, class I2cMultiplexerDevice > +class I2cMultiplexer : public i2cMultiplexer, public modm::I2c +{ +public: + /// Constructor, sets address to default of 0x70 + I2cMultiplexer(); + + static bool + start(I2cTransaction *transaction, ConfigurationHandler handler = nullptr) + { + return I2cMaster::start(transaction, handler); + } + +public: + /// Alias-templates for simpler use of the Channels + /// @{ + template < auto &object > + using Ch0 = I2cMultiplexerChannel< object, Channel::Ch0 >; + template < auto &object > + using Ch1 = I2cMultiplexerChannel< object, Channel::Ch1 >; + template < auto &object > + using Ch2 = I2cMultiplexerChannel< object, Channel::Ch2 >; + template < auto &object > + using Ch3 = I2cMultiplexerChannel< object, Channel::Ch3 >; + template < auto &object > + using Ch4 = I2cMultiplexerChannel< object, Channel::Ch4 >; + template < auto &object > + using Ch5 = I2cMultiplexerChannel< object, Channel::Ch5 >; + template < auto &object > + using Ch6 = I2cMultiplexerChannel< object, Channel::Ch6 >; + template < auto &object > + using Ch7 = I2cMultiplexerChannel< object, Channel::Ch7 >; + /// @} + + I2cMultiplexerDevice multiplexerDevice; +}; + +} // modm namespace + +template < class I2cMaster, class I2cMultiplexerDevice > +modm::I2cMultiplexer::I2cMultiplexer() +{ +} + +template < + auto &multiplexer, + typename std::remove_reference_t::Channel channel > +bool +modm::I2cMultiplexerChannel::start(modm::I2cTransaction *transaction, ConfigurationHandler handler) +{ + // If call to multiplexer failed, return without doing the actual transaction + if (RF_CALL_BLOCKING(multiplexer.multiplexerDevice.setActiveChannel(static_cast(channel))) == false) { + return false; + } + + return multiplexer.start(transaction, handler); +} + +#endif // MODM_I2C_MULTIPLEXER_HPP diff --git a/src/modm/architecture/module.lb b/src/modm/architecture/module.lb index a9faafe426..102564ea23 100644 --- a/src/modm/architecture/module.lb +++ b/src/modm/architecture/module.lb @@ -206,6 +206,20 @@ class I2cDevice(Module): env.copy("interface/i2c_device.hpp") # ----------------------------------------------------------------------------- +class I2cMultiplexer(Module): + def init(self, module): + module.name = "i2c.multiplexer" + module.description = "I²C Multiplexer" + + def prepare(self, module, options): + module.depends(":architecture:i2c", ":architecture:register", ":processing:resumable", ":math:utils") + return True + + def build(self, env): + env.outbasepath = "modm/src/modm/architecture" + env.copy("interface/i2c_multiplexer.hpp") +# ----------------------------------------------------------------------------- + class Interrupt(Module): def init(self, module): module.name = "interrupt" @@ -342,6 +356,7 @@ def prepare(module, options): module.add_submodule(Heap()) module.add_submodule(I2c()) module.add_submodule(I2cDevice()) + module.add_submodule(I2cMultiplexer()) module.add_submodule(Interrupt()) module.add_submodule(Memory()) module.add_submodule(OneWire())