From db0ee2726ac207deb6ec3457b5c02371b2835efd Mon Sep 17 00:00:00 2001 From: Stefan de Bruijn Date: Sun, 13 Jun 2021 22:40:42 +0200 Subject: [PATCH] Added basic pin mapper to map Pin objects to Arduino API --- Grbl_Esp32/src/PinMapper.cpp | 13 ++++++++++--- Grbl_Esp32/src/PinMapper.h | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Grbl_Esp32/src/PinMapper.cpp b/Grbl_Esp32/src/PinMapper.cpp index 2f0bdb71..ee3c1a87 100644 --- a/Grbl_Esp32/src/PinMapper.cpp +++ b/Grbl_Esp32/src/PinMapper.cpp @@ -4,8 +4,9 @@ #include -// Pin mapping. Pretty straight forward, it's just a thing that - +// Pin mapping. Pretty straight forward, it's just a thing that stores pins in an array. +// +// The default behavior of a mapped pin is _undefined pin_, so it does nothing. namespace { class Mapping { public: @@ -37,18 +38,24 @@ namespace { }; } +// See header file for more information. + PinMapper::PinMapper() : _mappedId(0) {} PinMapper::PinMapper(Pin& pin) { _mappedId = Mapping::instance().Claim(&pin); + + // If you reach this assertion, you haven't been using the Pin class like you're supposed to. Assert(_mappedId != 0, "Cannot claim pin. We've reached the limit of 255 mapped pins."); } +// To aid return values and assignment PinMapper::PinMapper(PinMapper&& o) : _mappedId(0) { std::swap(_mappedId, o._mappedId); } PinMapper& PinMapper::operator=(PinMapper&& o) { + // Special case for `a=a`. If we release there, things go wrong. if (&o != this) { if (_mappedId != 0) { Mapping::instance().Release(_mappedId); @@ -59,6 +66,7 @@ PinMapper& PinMapper::operator=(PinMapper&& o) { return *this; } +// Clean up when we get destructed. PinMapper::~PinMapper() { if (_mappedId != 0) { Mapping::instance().Release(_mappedId); @@ -66,7 +74,6 @@ PinMapper::~PinMapper() { } // Arduino compatibility functions, which basically forward the call to the mapper: - void IRAM_ATTR digitalWrite(uint8_t pin, uint8_t val) { auto thePin = Mapping::instance()._mapping[pin]; if (thePin) { diff --git a/Grbl_Esp32/src/PinMapper.h b/Grbl_Esp32/src/PinMapper.h index 51a6a397..bc049482 100644 --- a/Grbl_Esp32/src/PinMapper.h +++ b/Grbl_Esp32/src/PinMapper.h @@ -2,6 +2,11 @@ // Pin mapper is a class that maps 'Pin' objects to Arduino digitalWrite / digitalRead / setMode. This // can be useful for support of external libraries, while keeping all the things that Pin has to offer. +// +// It's designed to be easy to use. Basically just: `PinMapper myMap(pinToMap);`. It doesn't *own* the +// pin, it merely uses a pointer. Then, the external library can use `myMap.pinId()` as its pin number. +// Once the mapper goes out of scope (or is destructed if it's a field), the mapping is implicitly removed. +// Note that this is merely for external libraries that don't allow us to pass user data such as a void*... #include "Pin.h" @@ -9,16 +14,26 @@ class PinMapper { uint8_t _mappedId; public: + // Default constructor. Doesn't map anything PinMapper(); + + // Constructor that maps a pin to some Arduino pin ID PinMapper(Pin& pin); + // Let's not create copies, that will go wrong... PinMapper(const Pin& o) = delete; PinMapper& operator=(const Pin& o) = delete; + // For return values, we have to add some move semantics. This is just to + // support trivial assignment cases and return values. Normally: don't use it. + // All these constructors just pass along the id by swapping it. If a pinmapper + // goes out of scope, it is destructed. PinMapper(PinMapper&& o); PinMapper& operator=(PinMapper&& o); + // The ID of the pin, as used by digitalWrite, digitalRead and setMode. inline uint8_t pinId() const { return _mappedId; } + // Destructor. Implicitly removes the mapping. ~PinMapper(); };