Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/GPIO
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2020-02-12 23:51:56 +0300
committerDavid Crocker <dcrocker@eschertech.com>2020-02-12 23:51:56 +0300
commit9885ed7cc55cb19fde1be14c8adfd11dfa7f86cf (patch)
tree43f81c1a73028b5ecc516854c20601d63d0f119e /src/GPIO
parentd27f0a701c84fe1fcf4dc99c067b1fc38cd90f91 (diff)
Refactored GP inputs
Diffstat (limited to 'src/GPIO')
-rw-r--r--src/GPIO/GpioPorts.cpp237
-rw-r--r--src/GPIO/GpioPorts.h71
2 files changed, 308 insertions, 0 deletions
diff --git a/src/GPIO/GpioPorts.cpp b/src/GPIO/GpioPorts.cpp
new file mode 100644
index 00000000..3ee8b45f
--- /dev/null
+++ b/src/GPIO/GpioPorts.cpp
@@ -0,0 +1,237 @@
+/*
+ * GpioPorts.cpp
+ *
+ * Created on: 11 Feb 2020
+ * Author: David
+ */
+
+#include "GpioPorts.h"
+#include <GCodes/GCodeBuffer/GCodeBuffer.h>
+#include <RepRap.h>
+#include <Platform.h>
+
+#if SUPPORT_CAN_EXPANSION
+# include <CAN/CanInterface.h>
+# include <CAN/CanMessageGenericConstructor.h>
+#endif
+
+#if SUPPORT_OBJECT_MODEL
+
+// Object model table and functions
+// Note: if using GCC version 7.3.1 20180622 and lambda functions are used in this table, you must compile this file with option -std=gnu++17.
+// Otherwise the table will be allocated in RAM instead of flash, which wastes too much RAM.
+
+// Macro to build a standard lambda function that includes the necessary type conversions
+#define OBJECT_MODEL_FUNC(...) OBJECT_MODEL_FUNC_BODY(GpInputPort, __VA_ARGS__)
+
+constexpr ObjectModelTableEntry GpInputPort::objectModelTable[] =
+{
+ // Within each group, these entries must be in alphabetical order
+ // 0. sensors members
+ { "configured", OBJECT_MODEL_FUNC(!self->IsUnused()), ObjectModelEntryFlags::none },
+ { "value", OBJECT_MODEL_FUNC(self->GetState()), ObjectModelEntryFlags::live },
+};
+
+constexpr uint8_t GpInputPort::objectModelTableDescriptor[] = { 1, 2 };
+
+DEFINE_GET_OBJECT_MODEL_TABLE(GpInputPort)
+
+#endif
+
+bool GpInputPort::GetState() const noexcept
+{
+ // Temporary implementation until we use interrupts to track input pin state changes
+#if SUPPORT_CAN_EXPANSION
+ if (boardAddress != CanId::MasterAddress)
+ {
+ return currentState;
+ }
+#endif
+ return port.Read();
+}
+
+// Return true if the port is not configured
+bool GpInputPort::IsUnused() const noexcept
+{
+ return
+#if SUPPORT_CAN_EXPANSION
+ boardAddress == CanId::MasterAddress &&
+#endif
+ !port.IsValid();
+}
+
+GCodeResult GpInputPort::Configure(uint32_t gpinNumber, GCodeBuffer &gb, const StringRef &reply)
+{
+ if (gb.Seen('C'))
+ {
+ String<StringLength50> pinName;
+ gb.GetReducedString(pinName.GetRef());
+
+ // Remove any existing assignment
+#if SUPPORT_CAN_EXPANSION
+ if (boardAddress != CanId::MasterAddress)
+ {
+ if (CanInterface::DeleteHandle(boardAddress, handle, reply) != GCodeResult::ok)
+ {
+ reprap.GetPlatform().Message(AddWarning(gb.GetResponseMessageType()), reply.c_str());
+ }
+ boardAddress = CanId::MasterAddress;
+ }
+#endif
+ port.Release();
+ currentState = false;
+
+#if SUPPORT_CAN_EXPANSION
+ const CanAddress newBoard = IoPort::RemoveBoardAddress(pinName.GetRef());
+ if (newBoard != CanId::MasterAddress)
+ {
+ handle.Set(RemoteInputHandle::typeGpIn, gpinNumber, 0);
+ const GCodeResult rslt = CanInterface::CreateHandle(newBoard, handle, pinName.c_str(), 0, MinimumGpinReportInterval, currentState, reply);
+ if (rslt == GCodeResult::ok)
+ {
+ boardAddress = newBoard;
+ }
+ else
+ {
+ currentState = false;
+ }
+ return rslt;
+ }
+#endif
+ if (!port.AssignPort(pinName.c_str(), reply, PinUsedBy::gpin, PinAccess::read))
+ {
+ return GCodeResult::error;
+ }
+ currentState = port.Read();
+ }
+ else
+ {
+ // Report the pin details
+#if SUPPORT_CAN_EXPANSION
+ if (boardAddress != CanId::MasterAddress)
+ {
+ const GCodeResult rslt = CanInterface::GetHandlePinName(boardAddress, handle, currentState, reply);
+ if (rslt != GCodeResult::ok)
+ {
+ return rslt;
+ }
+ reply.Prepend("Pin ");
+ }
+ else
+#endif
+ {
+ reply.copy("Pin ");
+ port.AppendPinName(reply);
+ }
+ reply.catf(", active: %s", (currentState) ? "true" : "false");
+ }
+ return GCodeResult::ok;
+}
+
+GCodeResult GpOutputPort::Configure(uint32_t gpioNumber, bool isServo, GCodeBuffer &gb, const StringRef &reply)
+{
+ PwmFrequency freq = 0;
+ const bool seenFreq = gb.Seen('Q');
+ if (seenFreq)
+ {
+ freq = gb.GetPwmFrequency();
+ }
+
+ if (gb.Seen('C'))
+ {
+ String<StringLength50> pinName;
+ gb.GetReducedString(pinName.GetRef());
+
+ // Remove any existing assignment
+#if SUPPORT_CAN_EXPANSION
+ if (boardAddress != CanId::MasterAddress)
+ {
+ CanMessageGenericConstructor cons(M950GpioParams);
+ cons.AddUParam('P', gpioNumber);
+ cons.AddStringParam('C', NoPinName);
+ if (cons.SendAndGetResponse(CanMessageType::m950Gpio, boardAddress, reply) != GCodeResult::ok)
+ {
+ reprap.GetPlatform().Message(WarningMessage, reply.c_str());
+ reply.Clear();
+ }
+ boardAddress = CanId::MasterAddress;
+ }
+#endif
+ port.Release();
+
+ if (!seenFreq)
+ {
+ freq = (isServo) ? ServoRefreshFrequency : DefaultPinWritePwmFreq;
+ }
+
+#if SUPPORT_CAN_EXPANSION
+ boardAddress = IoPort::RemoveBoardAddress(pinName.GetRef());
+ if (boardAddress != CanId::MasterAddress)
+ {
+ CanMessageGenericConstructor cons(M950GpioParams);
+ cons.AddUParam('P', gpioNumber);
+ cons.AddUParam('Q', freq);
+ cons.AddUParam('S', (isServo) ? 1 : 0);
+ cons.AddStringParam('C', pinName.c_str());
+ return cons.SendAndGetResponse(CanMessageType::m950Gpio, boardAddress, reply);
+ }
+#endif
+ if (!port.AssignPort(pinName.c_str(), reply, PinUsedBy::gpout, (isServo) ? PinAccess::servo : PinAccess::pwm))
+ {
+ return GCodeResult::error;
+ }
+ port.SetFrequency(freq);
+ }
+ else if (seenFreq)
+ {
+#if SUPPORT_CAN_EXPANSION
+ if (boardAddress != CanId::MasterAddress)
+ {
+ CanMessageGenericConstructor cons(M950GpioParams);
+ cons.AddUParam('P', gpioNumber);
+ cons.AddUParam('Q', freq);
+ return cons.SendAndGetResponse(CanMessageType::m950Gpio, boardAddress, reply);
+ }
+#endif
+ port.SetFrequency(freq);
+ }
+ else
+ {
+#if SUPPORT_CAN_EXPANSION
+ if (boardAddress != CanId::MasterAddress)
+ {
+ CanMessageGenericConstructor cons(M950GpioParams);
+ cons.AddUParam('P', gpioNumber);
+ return cons.SendAndGetResponse(CanMessageType::m950Gpio, boardAddress, reply);
+ }
+#endif
+ reply.printf("GPIO/servo port %" PRIu32, gpioNumber);
+ port.AppendDetails(reply);
+ }
+ return GCodeResult::ok;
+}
+
+GCodeResult GpOutputPort::WriteAnalog(uint32_t gpioPortNumber, bool isServo, float pwm, const GCodeBuffer& gb, const StringRef& reply) const noexcept
+{
+#if SUPPORT_CAN_EXPANSION
+ if (boardAddress != CanId::MasterAddress)
+ {
+ return CanInterface::WriteGpio(boardAddress, gpioPortNumber, pwm, isServo, gb, reply);
+ }
+#endif
+ port.WriteAnalog(pwm);
+ return GCodeResult::ok;
+}
+
+#ifdef PCCB
+
+// Function used to assign default GPOUT devices
+void GpOutputPort::Assign(const char *pinName) noexcept
+{
+ String<1> dummy;
+ port.AssignPort(pinName, dummy.GetRef(), PinUsedBy::gpout, PinAccess::pwm);
+}
+
+#endif
+
+// End
diff --git a/src/GPIO/GpioPorts.h b/src/GPIO/GpioPorts.h
new file mode 100644
index 00000000..b8290c28
--- /dev/null
+++ b/src/GPIO/GpioPorts.h
@@ -0,0 +1,71 @@
+/*
+ * GpioPorts.h
+ *
+ * Created on: 11 Feb 2020
+ * Author: David
+ */
+
+#ifndef SRC_GPIO_GPIOPORTS_H_
+#define SRC_GPIO_GPIOPORTS_H_
+
+#include <RepRapFirmware.h>
+#include <Hardware/IoPorts.h>
+#include <GCodes/GCodeResult.h>
+#include <ObjectModel/ObjectModel.h>
+
+#if SUPPORT_CAN_EXPANSION
+# include <RemoteInputHandle.h>
+#endif
+
+class GpInputPort INHERIT_OBJECT_MODEL
+{
+public:
+ GpInputPort() noexcept :
+#if SUPPORT_CAN_EXPANSION
+ boardAddress (CanId::MasterAddress),
+#endif
+ currentState(false) { }
+
+ bool GetState() const noexcept;
+ bool IsUnused() const noexcept;
+
+#if SUPPORT_CAN_EXPANSION
+ void SetState(CanAddress src, bool b) noexcept { if (src == boardAddress) { currentState = b; } }
+#endif
+
+ GCodeResult Configure(uint32_t gpinNumber, GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException);
+
+protected:
+ DECLARE_OBJECT_MODEL
+
+private:
+ IoPort port; // will be initialised by PwmPort default constructor
+#if SUPPORT_CAN_EXPANSION
+ RemoteInputHandle handle;
+ CanAddress boardAddress;
+#endif
+ bool currentState;
+};
+
+class GpOutputPort
+{
+public:
+#if SUPPORT_CAN_EXPANSION
+ GpOutputPort() noexcept { boardAddress = CanId::MasterAddress; }
+#endif
+
+ GCodeResult WriteAnalog(uint32_t gpioPortNumber, bool isServo, float pwm, const GCodeBuffer& gb, const StringRef& reply) const noexcept;
+ GCodeResult Configure(uint32_t gpioNumber, bool isServo, GCodeBuffer& gb, const StringRef& reply) THROWS(GCodeException);
+
+#ifdef PCCB
+ void Assign(const char *pinName) noexcept;
+#endif
+
+private:
+ PwmPort port; // will be initialised by PwmPort default constructor
+#if SUPPORT_CAN_EXPANSION
+ CanAddress boardAddress;
+#endif
+};
+
+#endif /* SRC_GPIO_GPIOPORTS_H_ */