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
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2018-08-29 20:32:40 +0300
committerDavid Crocker <dcrocker@eschertech.com>2018-08-29 20:32:40 +0300
commit06335b899c408cdf1539425b9d918f43d5ccfbdc (patch)
tree90e4c7a217374167747185ff3d4440c0d78c2c65 /src
parent413586e519ce77215d9bee808cc62cf0e6ac6f79 (diff)
More work towards 2.02beta2
Duet Maestro 12864 display: merged in Matt's changes and did some fixes Changed Smart Drivers interface to support accessing additional registers and parts of registers Started implementing an object model Change C++ compilation mode to gnu++17 to handle lambda function pointers in flash memory Added NamedEnum class *(notuzsed yet)
Diffstat (limited to 'src')
-rw-r--r--src/BugList.txt14
-rw-r--r--src/Display/Menu.cpp127
-rw-r--r--src/Display/Menu.h9
-rw-r--r--src/GCodes/DriverMode.h27
-rw-r--r--src/GCodes/GCodes.cpp27
-rw-r--r--src/GCodes/GCodes.h11
-rw-r--r--src/GCodes/GCodes2.cpp8
-rw-r--r--src/Libraries/General/SafeVsnprintf.cpp2
-rw-r--r--src/Movement/StepperDrivers/DriverMode.cpp (renamed from src/GCodes/DriverMode.cpp)0
-rw-r--r--src/Movement/StepperDrivers/DriverMode.h42
-rw-r--r--src/Movement/StepperDrivers/TMC22xx.cpp140
-rw-r--r--src/Movement/StepperDrivers/TMC22xx.h9
-rw-r--r--src/Movement/StepperDrivers/TMC2660.cpp163
-rw-r--r--src/Movement/StepperDrivers/TMC2660.h9
-rw-r--r--src/Movement/StepperDrivers/TMC51xx.cpp50
-rw-r--r--src/Movement/StepperDrivers/TMC51xx.h7
-rw-r--r--src/NamedEnum.h53
-rw-r--r--src/ObjectModel/ObjectModel.cpp308
-rw-r--r--src/ObjectModel/ObjectModel.h160
-rw-r--r--src/Platform.cpp2
-rw-r--r--src/RepRap.cpp27
-rw-r--r--src/RepRap.h12
-rw-r--r--src/Version.h2
23 files changed, 937 insertions, 272 deletions
diff --git a/src/BugList.txt b/src/BugList.txt
index c8fa66b8..635846bf 100644
--- a/src/BugList.txt
+++ b/src/BugList.txt
@@ -28,12 +28,24 @@ Implemented in 2.02beta1:
- PCCB build: endstop 0 and 1 are now assigned to Z and X respectively
- added check for timeout when sending to the W5500 but not receiving
+Investigations:
+- Weird height map, https://forum.duet3d.com/topic/6472/mesh-grid-compensation/28
+- Full stepping problem, https://forum.duet3d.com/topic/6433/how-to-reduce-the-speed-of-extrusion/14
+- Print time estimation problem, see https://forum.duet3d.com/topic/5572/it-s-out-reprapfirmware-2-0-and-1-21-1-released/64
+- Disconnections, https://forum.duet3d.com/topic/6487/running-bed-mesh-compensation/19
+
Remaining:
- [done, ok on DuetM, test on Duet2] No warning messages when TMC2224 drivers overheat, https://forum.duet3d.com/topic/6309/little-monster-s-hort-to-ground/13
+- [done] Different numbers of endstop inputs and motor drivers
+- Check M106 R1 parameter, see https://forum.duet3d.com/topic/6538/resuming-print-fan-after-pause
+- Support mixed stealthchop/spread cycle mode on Maestro via TPWMTHRS register, https://forum.duet3d.com/topic/6512/duet-2-maestro-stealthchop-default/7
+- Add check digit to serial number
+- check DAA working as intended, results are inconsistent
+- chrishamm's watchdog issue, see his email oif 2018-08-01
- G30 S-1 when no Z probe, https://forum.duet3d.com/topic/6510/a-couple-of-dwc-odd-things/2
- Command to copy output from the following commands to the log file?
- Track which devices use which pins
-- Matt's display changes/other display fixes
+- [done, M3D testing] Merge in Matt's display changes
- Hangprinter PRs
- PR to have any enabled driver report 50C
- PR to allow endstop input number to be specified in M558
diff --git a/src/Display/Menu.cpp b/src/Display/Menu.cpp
index d530f548..1a30cc99 100644
--- a/src/Display/Menu.cpp
+++ b/src/Display/Menu.cpp
@@ -21,7 +21,7 @@
* Wnn is the width in pixels for the element
* Dnn specifies the number of decimal places for numeric display
*
- * Vnn specifies the item's visibility with value:
+ * Vnn specifies the item's visibility (currently implemented for buttons only) with value:
* 0 always visible (default if not specified)
* 2 visible when the printer is actively printing (actively printing defined as not paused, pausing or resuming)
* 3 visible when the printer is NOT actively printing
@@ -31,6 +31,8 @@
* 7 visible when the printer is printing and NOT in paused state (actively printing or resuming)
* 10 visible when SD card 0 is mounted
* 11 visible when SD card 0 is NOT mounted
+ * 20 visible when the current or default tool has a temperature fault
+ * 28 visible when the bed heater has a temperature fault
*
* "action" can be any of:
* - a Gcode command string (must begin with G, M or T). In such a string, #0 represents the full name of the current file, in double quotes, set when a file is selected
@@ -74,11 +76,14 @@
#include "Storage/MassStorage.h"
#include "Tools/Tool.h"
+const uint32_t InactivityTimeout = 20000; // inactivity timeout
+const uint32_t ErrorTimeout = 6000; // how long wre display an error message for
+
Menu::Menu(Lcd7920& refLcd, const LcdFont * const fnts[], size_t nFonts)
: lcd(refLcd), fonts(fnts), numFonts(nFonts),
- timeoutEnabled(false), lastActionTime(millis()),
- selectableItems(nullptr), unSelectableItems(nullptr), numNestedMenus(0), numSelectableItems(0), highlightedItem(0), itemIsSelected(false),
- rowOffset(0)
+ timeoutValue(0), lastActionTime(0),
+ selectableItems(nullptr), unSelectableItems(nullptr), numNestedMenus(0), numSelectableItems(0), highlightedItem(0), itemIsSelected(false), displayingFixedMenu(false),
+ errorColumn(0), rowOffset(0)
{
}
@@ -111,56 +116,46 @@ void Menu::Load(const char* filename)
}
++numNestedMenus;
+ displayingFixedMenu = false;
Reload();
}
}
void Menu::LoadFixedMenu()
{
- if (numNestedMenus < MaxMenuNesting)
- {
- filenames[numNestedMenus].copy(m_pcFixedMenu);
-
- rowOffset = 0;
-
- currentMargin = 0;
- lcd.Clear();
-
- ++numNestedMenus;
-
- // Instead of Reload():
- lcd.SetRightMargin(NumCols - currentMargin);
+ displayingFixedMenu = true;
+ numNestedMenus = 0;
+ rowOffset = 0;
+ currentMargin = 0;
+ lcd.Clear();
- ResetCache();
+ // Instead of Reload():
+ lcd.SetRightMargin(NumCols - currentMargin);
- char acLine1[] = "text R3 C5 F0 T\"No SD Card Found\"";
- char acLine2[] = "button R15 C5 F0 T\"Mount SD\" A\"M21\"";
+ ResetCache();
- const char *errMsg = ParseMenuLine(acLine1);
- if (nullptr != errMsg)
- {
- LoadError(errMsg, 1);
- }
- if (commandBufferIndex == sizeof(commandBuffer))
- {
- LoadError("|Menu buffer full", 1);
- }
+ char acLine1[] = "text R3 C5 F0 T\"No SD Card Found\"";
+ char acLine2[] = "button R15 C5 F0 T\"Mount SD\" A\"M21\"";
- errMsg = ParseMenuLine(acLine2);
- if (nullptr != errMsg)
- {
- LoadError(errMsg, 2);
- }
- if (commandBufferIndex == sizeof(commandBuffer))
- {
- LoadError("|Menu buffer full", 2);
- }
+ const char *errMsg = ParseMenuLine(acLine1);
+ if (nullptr != errMsg)
+ {
+ LoadError(errMsg, 1);
+ }
+ if (commandBufferIndex == sizeof(commandBuffer))
+ {
+ LoadError("|Menu buffer full", 1);
}
-}
-bool Menu::bInFixedMenu() const
-{
- return ((0 != numNestedMenus) && (0 == strcmp(filenames[numNestedMenus - 1].c_str(), m_pcFixedMenu)));
+ errMsg = ParseMenuLine(acLine2);
+ if (nullptr != errMsg)
+ {
+ LoadError(errMsg, 2);
+ }
+ if (commandBufferIndex == sizeof(commandBuffer))
+ {
+ LoadError("|Menu buffer full", 2);
+ }
}
void Menu::Pop()
@@ -179,26 +174,31 @@ void Menu::LoadError(const char *msg, unsigned int line)
lcd.Clear(currentMargin, currentMargin, NumRows - currentMargin, NumCols - currentMargin);
lcd.SetFont(fonts[0]);
- lcd.print("Error loading menu\nFile ");
- lcd.print(filenames[numNestedMenus - 1].c_str());
+ lcd.print("Error loading menu\nFile: ");
+ lcd.print((numNestedMenus > 0) ? filenames[numNestedMenus - 1].c_str() : "(none)");
if (line != 0)
{
lcd.print("\nLine ");
lcd.print(line);
+ if (errorColumn != 0)
+ {
+ lcd.print(" column ");
+ lcd.print(errorColumn);
+ }
}
lcd.write('\n');
lcd.print(msg);
- if (numNestedMenus > 1)
- {
- // TODO add control to pop previous menu here, or revert to main menu after some time
- }
+ lastActionTime = millis();
+ timeoutValue = ErrorTimeout;
}
// Parse a line in a menu layout file returning any error message, or nullptr if there was no error.
// Leading whitespace has already been skipped.
-const char *Menu::ParseMenuLine(char *commandWord)
+const char *Menu::ParseMenuLine(char * const commandWord)
{
+ errorColumn = 0;
+
// Check for blank or comment line
if (*commandWord == ';' || *commandWord == 0)
{
@@ -213,12 +213,13 @@ const char *Menu::ParseMenuLine(char *commandWord)
}
if (args == commandWord || (*args != ' ' && *args != '\t' && *args != 0))
{
+ errorColumn = (args - commandWord) + 1;
return "Bad command";
}
if (*args != 0)
{
- *args = 0; // null terminate command word
+ *args = 0; // null terminate the command word
++args;
}
@@ -275,6 +276,7 @@ const char *Menu::ParseMenuLine(char *commandWord)
case 'I':
if (*args != '"')
{
+ errorColumn = (args - commandWord) + 1;
return "Missing string arg";
}
++args;
@@ -291,6 +293,7 @@ const char *Menu::ParseMenuLine(char *commandWord)
break;
default:
+ errorColumn = (args - commandWord);
return "Bad arg letter";
}
}
@@ -349,12 +352,13 @@ const char *Menu::ParseMenuLine(char *commandWord)
const char * const actionString = AppendString(action);
const char *const dir = AppendString(dirpath);
const char *const acFileString = AppendString(fname);
- AddItem(new FilesMenuItem(row, column, fontNumber, actionString, dir, acFileString, nparam, fonts[fontNumber]->height), true);
- //TODO update row by a sensible value e.g. nparam * text row height
+ AddItem(new FilesMenuItem(row, 0, fontNumber, actionString, dir, acFileString, nparam, fonts[fontNumber]->height), true);
+ row += nparam * fonts[fontNumber]->height;
column = 0;
}
else
{
+ errorColumn = 1;
return "Unknown command";
}
@@ -366,13 +370,13 @@ void Menu::ResetCache()
// Delete the existing items
while (selectableItems != nullptr)
{
- MenuItem *current = selectableItems;
+ MenuItem * const current = selectableItems;
selectableItems = selectableItems->GetNext();
delete current;
}
while (unSelectableItems != nullptr)
{
- MenuItem *current = unSelectableItems;
+ MenuItem * const current = unSelectableItems;
unSelectableItems = unSelectableItems->GetNext();
delete current;
}
@@ -587,8 +591,8 @@ void Menu::EncoderAction(int action)
EncoderAction_EnterItemHelper();
}
- timeoutEnabled = true;
lastActionTime = millis();
+ timeoutValue = InactivityTimeout;
}
/*static*/ const char *Menu::SkipWhitespace(const char *s)
{
@@ -611,7 +615,7 @@ void Menu::EncoderAction(int action)
void Menu::LoadImage(const char *fname)
{
//TODO
- lcd.print("<image>");
+ lcd.print("[img]");
}
// Refresh is called every Spin() of the Display under most circumstances; an appropriate place to check if timeout action needs to be taken
@@ -619,23 +623,20 @@ void Menu::Refresh()
{
if (!reprap.GetPlatform().GetMassStorage()->IsDriveMounted(0))
{
- if (!bInFixedMenu())
+ if (!displayingFixedMenu)
{
// When the SD card is not mounted, we show a fixed menu for graceful recovery
- numNestedMenus = 0;
LoadFixedMenu();
}
}
- else if (bInFixedMenu() || (timeoutEnabled && (millis() - lastActionTime > 20000)))
+ else if (displayingFixedMenu || (timeoutValue != 0 && (millis() - lastActionTime > timeoutValue)))
{
- // Showing fixed menu but SD card is now mounted, or 20 seconds following latest user action
-
+ // Showing fixed menu but SD card is now mounted, or 10 seconds following latest user action
// Go to the top menu (just discard information)
numNestedMenus = 0;
Load("main");
- timeoutEnabled = false;
- // m_uLastActionTime = millis();
+ timeoutValue = 0;
}
const PixelNumber rightMargin = NumCols - currentMargin;
diff --git a/src/Display/Menu.h b/src/Display/Menu.h
index e6658c64..925338f1 100644
--- a/src/Display/Menu.h
+++ b/src/Display/Menu.h
@@ -23,10 +23,9 @@ public:
private:
void LoadFixedMenu();
- bool bInFixedMenu() const;
void ResetCache();
void Reload();
- const char *ParseMenuLine(char *s);
+ const char *ParseMenuLine(char * s);
void LoadError(const char *msg, unsigned int line);
void AddItem(MenuItem *item, bool isSelectable);
const char *AppendString(const char *s);
@@ -54,7 +53,7 @@ private:
const LcdFont * const *fonts;
const size_t numFonts;
- bool timeoutEnabled;
+ uint32_t timeoutValue; // how long to time out after 0 = no timeout
uint32_t lastActionTime;
MenuItem *selectableItems; // selectable items at the innermost level
@@ -64,11 +63,11 @@ private:
int numSelectableItems;
int highlightedItem;
bool itemIsSelected;
-
- static constexpr const char *const m_pcFixedMenu = "zzFixed";
+ bool displayingFixedMenu;
// Variables used while parsing
size_t commandBufferIndex;
+ unsigned int errorColumn; // column in the current line at which ParseMenuLine hit an error
MenuItem::FontNumber fontNumber;
PixelNumber currentMargin;
PixelNumber row, column;
diff --git a/src/GCodes/DriverMode.h b/src/GCodes/DriverMode.h
deleted file mode 100644
index 594fbcf3..00000000
--- a/src/GCodes/DriverMode.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * DriverModes.h
- *
- * Created on: 27 Apr 2018
- * Author: David
- */
-
-#ifndef SRC_GCODES_DRIVERMODE_H_
-#define SRC_GCODES_DRIVERMODE_H_
-
-enum class DriverMode : unsigned int
-{
- constantOffTime = 0,
- randomOffTime,
- spreadCycle,
- stealthChop, // includes stealthChop2
- unknown // must be last!
-};
-
-const char* TranslateDriverMode(unsigned int mode);
-
-inline const char* TranslateDriverMode(DriverMode mode)
-{
- return TranslateDriverMode((unsigned int)mode);
-}
-
-#endif /* SRC_GCODES_DRIVERMODE_H_ */
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index 88c1c9fb..aca91dfe 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -59,6 +59,33 @@ void GCodes::RawMove::SetDefaults()
yAxes = DefaultYAxisMapping;
}
+#ifdef SUPPORT_OBJECT_MODEL
+
+// Object model table and functions
+// Note: if using GCC version 7.3.1 20180622 then if lambda functions are used in this table, you must compile this file with option -std=gnu++17.
+// Otherwise the table will be allocate 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(_ret) [] (ObjectModel* arg) { GCodes * const self = static_cast<GCodes*>(arg); return (void *)(_ret); }
+
+const ObjectModelTableEntry GCodes::objectModelTable[] =
+{
+ { "speedFactor", OBJECT_MODEL_FUNC(&(self->speedFactor)), TYPE_OF(float), ObjectModelTableEntry::none }
+};
+
+const char *GCodes::GetModuleName() const
+{
+ return nullptr; // this module has no name and doesn't need one
+}
+
+const ObjectModelTableEntry *GCodes::GetObjectModelTable(size_t& numEntries) const
+{
+ numEntries = ARRAY_SIZE(objectModelTable);
+ return objectModelTable;
+}
+
+#endif
+
GCodes::GCodes(Platform& p) :
platform(p), machineType(MachineType::fff), active(false),
#if HAS_VOLTAGE_MONITOR
diff --git a/src/GCodes/GCodes.h b/src/GCodes/GCodes.h
index 7afa207f..1e7da7e4 100644
--- a/src/GCodes/GCodes.h
+++ b/src/GCodes/GCodes.h
@@ -105,6 +105,9 @@ enum class StopPrintReason
// The GCode interpreter
class GCodes
+#ifdef SUPPORT_OBJECT_MODEL
+ : public ObjectModel
+#endif
{
public:
struct RawMove
@@ -226,6 +229,14 @@ public:
void HandleReply(GCodeBuffer& gb, GCodeResult rslt, const char *reply); // Handle G-Code replies
void EmergencyStop(); // Cancel everything
+#ifdef SUPPORT_OBJECT_MODEL
+protected:
+ const char *GetModuleName() const override;
+ const ObjectModelTableEntry *GetObjectModelTable(size_t& numEntries) const override;
+
+ static const ObjectModelTableEntry objectModelTable[];
+#endif
+
private:
GCodes(const GCodes&); // private copy constructor to prevent copying
diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp
index 81a5599c..9e75e2d9 100644
--- a/src/GCodes/GCodes2.cpp
+++ b/src/GCodes/GCodes2.cpp
@@ -20,6 +20,7 @@
#include "Tools/Tool.h"
#include "FilamentMonitors/FilamentMonitor.h"
#include "Libraries/General/IP4String.h"
+#include "Movement/StepperDrivers/DriverMode.h"
#include "Version.h"
#if SUPPORT_IOBITS
@@ -3197,7 +3198,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
if (gb.Seen('C')) // set chopper control register
{
seen = true;
- if (!SmartDrivers::SetChopperControlRegister(drive, gb.GetUIValue()))
+ if (!SmartDrivers::SetRegister(drive, SmartDriverRegister::chopperControl, gb.GetUIValue()))
{
reply.printf("Bad ccr for driver %u", drive);
result = GCodeResult::error;
@@ -3208,7 +3209,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
if (gb.Seen('F'))
{
seen = true;
- if (!SmartDrivers::SetOffTime(drive, gb.GetUIValue()))
+ if (!SmartDrivers::SetRegister(drive, SmartDriverRegister::toff, gb.GetUIValue()))
{
reply.printf("Bad off time for driver %u", drive);
result = GCodeResult::error;
@@ -3229,7 +3230,8 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
if (drive < platform.GetNumSmartDrivers())
{
reply.catf(", mode %s, ccr 0x%05" PRIx32 ", off time %" PRIu32,
- TranslateDriverMode(SmartDrivers::GetDriverMode(drive)), SmartDrivers::GetChopperControlRegister(drive), SmartDrivers::GetOffTime(drive));
+ TranslateDriverMode(SmartDrivers::GetDriverMode(drive)),
+ SmartDrivers::GetRegister(drive, SmartDriverRegister::chopperControl), SmartDrivers::GetRegister(drive, SmartDriverRegister::toff));
}
#endif
}
diff --git a/src/Libraries/General/SafeVsnprintf.cpp b/src/Libraries/General/SafeVsnprintf.cpp
index 9b171ce0..8e102cf0 100644
--- a/src/Libraries/General/SafeVsnprintf.cpp
+++ b/src/Libraries/General/SafeVsnprintf.cpp
@@ -527,7 +527,7 @@ static void tiny_print(SStringBuf& apBuf, const char *format, va_list args)
{
const char *s = va_arg(args, const char *);
apBuf.flags.isString = true;
- if (!prints(apBuf, (s != nullptr) ? s : "(null)"))
+ if (!prints(apBuf, (s != nullptr) ? s : "<null>"))
{
break;
}
diff --git a/src/GCodes/DriverMode.cpp b/src/Movement/StepperDrivers/DriverMode.cpp
index 6450e115..6450e115 100644
--- a/src/GCodes/DriverMode.cpp
+++ b/src/Movement/StepperDrivers/DriverMode.cpp
diff --git a/src/Movement/StepperDrivers/DriverMode.h b/src/Movement/StepperDrivers/DriverMode.h
new file mode 100644
index 00000000..4114120b
--- /dev/null
+++ b/src/Movement/StepperDrivers/DriverMode.h
@@ -0,0 +1,42 @@
+/*
+ * DriverModes.h
+ *
+ * Created on: 27 Apr 2018
+ * Author: David
+ */
+
+#ifndef SRC_MOVEMENT_STEPPERDRIVERS_DRIVERMODE_H_
+#define SRC_MOVEMENT_STEPPERDRIVERS_DRIVERMODE_H_
+
+enum class DriverMode : unsigned int
+{
+ constantOffTime = 0,
+ randomOffTime,
+ spreadCycle,
+ stealthChop, // includes stealthChop2
+ unknown // must be last!
+};
+
+const char* TranslateDriverMode(unsigned int mode);
+
+inline const char* TranslateDriverMode(DriverMode mode)
+{
+ return TranslateDriverMode((unsigned int)mode);
+}
+
+// Register codes used to implement M569 command parameters.
+// This common set is used for all smart drivers. Not all are complete registers, some are just parts of registers.
+
+enum class SmartDriverRegister : unsigned int
+{
+ toff,
+ tblank,
+ hstart,
+ hend,
+ hdec,
+ chopperControl,
+ coolStep,
+ tpwmthrs
+};
+
+#endif /* SRC_MOVEMENT_STEPPERDRIVERS_DRIVERMODE_H_ */
diff --git a/src/Movement/StepperDrivers/TMC22xx.cpp b/src/Movement/StepperDrivers/TMC22xx.cpp
index 0515be81..8f5570e1 100644
--- a/src/Movement/StepperDrivers/TMC22xx.cpp
+++ b/src/Movement/StepperDrivers/TMC22xx.cpp
@@ -140,7 +140,10 @@ constexpr uint32_t DefaultIholdIrunReg = (0 << IHOLDIRUN_IHOLD_SHIFT) | (0 << IH
constexpr uint8_t REGNUM_TPOWER_DOWN = 0x11;
constexpr uint8_t REGNUM_TSTEP = 0x12;
+
constexpr uint8_t REGNUM_TPWMTHRS = 0x13;
+constexpr uint32_t DefaultTpwmthrsReg = 1000; //TODO find a sensible default
+
constexpr uint8_t REGNUM_VACTUAL = 0x22;
// Sequencer registers (read only)
@@ -239,11 +242,6 @@ public:
void Init(uint32_t p_driverNumber, Pin p_pin);
void SetAxisNumber(size_t p_axisNumber);
void WriteAll();
- bool SetChopConf(uint32_t newVal);
- bool SetOffTime(uint32_t newVal);
- uint32_t GetChopConf() const;
- uint32_t GetOffTime() const;
- void SetCoolStep(uint16_t coolStepConfig);
bool SetMicrostepping(uint32_t shift, bool interpolate);
unsigned int GetMicrostepping(bool& interpolation) const; // Get microstepping
bool SetDriverMode(unsigned int mode);
@@ -255,6 +253,9 @@ public:
bool UpdatePending() const { return registersToUpdate != 0; }
bool UsesGlobalEnable() const { return enablePin == NoPin; }
+ bool SetRegister(SmartDriverRegister reg, uint32_t regVal);
+ uint32_t GetRegister(SmartDriverRegister reg) const;
+
float GetStandstillCurrentPercent() const;
void SetStandstillCurrentPercent(float percent);
@@ -273,6 +274,7 @@ public:
void UartTmcHandler(); // core of the ISR for this driver
private:
+ bool SetChopConf(uint32_t newVal);
void UpdateRegister(size_t regIndex, uint32_t regVal);
void UpdateChopConfRegister(); // calculate the chopper control register and flag it for sending
void UpdateCurrent();
@@ -286,7 +288,7 @@ private:
void SetupDMAReceive(uint8_t regnum, uint8_t crc) __attribute__ ((hot)); // set up the PDC to receive a register
#endif
- static constexpr unsigned int NumWriteRegisters = 5; // the number of registers that we write to
+ static constexpr unsigned int NumWriteRegisters = 6; // the number of registers that we write to
static const uint8_t WriteRegNumbers[NumWriteRegisters]; // the register numbers that we write to
// Write register numbers are in priority order, most urgent first, in same order as WriteRegNumbers
@@ -295,6 +297,7 @@ private:
static constexpr unsigned int WriteChopConf = 2; // enable/disable and microstep setting
static constexpr unsigned int WriteIholdIrun = 3; // current setting
static constexpr unsigned int WritePwmConf = 4; // read register select, sense voltage high/low sensitivity
+ static constexpr unsigned int WriteTpwmthrs = 5; // upper step rate limit for stealthchop
static constexpr unsigned int NumReadRegisters = 2; // the number of registers that we read from
static const uint8_t ReadRegNumbers[NumReadRegisters]; // the register numbers that we read from
@@ -374,7 +377,8 @@ const uint8_t TmcDriverState::WriteRegNumbers[NumWriteRegisters] =
REGNUM_SLAVECONF,
REGNUM_CHOPCONF,
REGNUM_IHOLDIRUN,
- REGNUM_PWMCONF
+ REGNUM_PWMCONF,
+ REGNUM_TPWMTHRS
};
const uint8_t TmcDriverState::ReadRegNumbers[NumReadRegisters] =
@@ -484,6 +488,7 @@ pre(!driversPowered)
SetMicrostepping(DefaultMicrosteppingShift, DefaultInterpolation); // this also updates the chopper control register
UpdateRegister(WriteIholdIrun, DefaultIholdIrunReg);
UpdateRegister(WritePwmConf, DefaultPwmConfReg);
+ UpdateRegister(WriteTpwmthrs, DefaultTpwmthrsReg);
for (size_t i = 0; i < NumReadRegisters; ++i)
{
accumulatedReadRegisters[i] = readRegisters[i] = 0;
@@ -536,40 +541,83 @@ unsigned int TmcDriverState::GetMicrostepping(bool& interpolation) const
return 1u << microstepShiftFactor;
}
-// Set the chopper control register to the settings provided by the user. We allow only the lowest 17 bits to be set.
-bool TmcDriverState::SetChopConf(uint32_t newVal)
+bool TmcDriverState::SetRegister(SmartDriverRegister reg, uint32_t regVal)
{
- const uint32_t offTime = (newVal & CHOPCONF_TOFF_MASK) >> CHOPCONF_TOFF_SHIFT;
- if (offTime == 0 || (offTime == 1 && (configuredChopConfReg & CHOPCONF_TBL_MASK) < (2 << CHOPCONF_TBL_SHIFT)))
+ switch(reg)
{
+ case SmartDriverRegister::chopperControl:
+ return SetChopConf(regVal);
+
+ case SmartDriverRegister::toff:
+ return SetChopConf((configuredChopConfReg & ~CHOPCONF_TOFF_MASK) | ((regVal << CHOPCONF_TOFF_SHIFT) & CHOPCONF_TOFF_MASK));
+
+ case SmartDriverRegister::tblank:
+ return SetChopConf((configuredChopConfReg & ~CHOPCONF_TBL_MASK) | ((regVal << CHOPCONF_TBL_SHIFT) & CHOPCONF_TBL_MASK));
+
+ case SmartDriverRegister::hstart:
+ return SetChopConf((configuredChopConfReg & ~CHOPCONF_HSTRT_MASK) | ((regVal << CHOPCONF_HSTRT_SHIFT) & CHOPCONF_HSTRT_MASK));
+
+ case SmartDriverRegister::hend:
+ return SetChopConf((configuredChopConfReg & ~CHOPCONF_HEND_MASK) | ((regVal << CHOPCONF_HEND_SHIFT) & CHOPCONF_HEND_MASK));
+
+ case SmartDriverRegister::tpwmthrs:
+ UpdateRegister(WriteTpwmthrs, regVal & ((1u << 20) - 1));
+ return true;
+
+ case SmartDriverRegister::hdec:
+ case SmartDriverRegister::coolStep:
+ default:
return false;
}
- const uint32_t userMask = CHOPCONF_TBL_MASK | CHOPCONF_HSTRT_MASK | CHOPCONF_HEND_MASK | CHOPCONF_TOFF_MASK; // mask of bits the user is allowed to change
- configuredChopConfReg = (configuredChopConfReg & ~userMask) | (newVal & userMask);
- UpdateChopConfRegister();
- return true;
}
-// Set the off time in the chopper control register
-bool TmcDriverState::SetOffTime(uint32_t newVal)
+uint32_t TmcDriverState::GetRegister(SmartDriverRegister reg) const
{
- if (newVal > 15)
+ switch(reg)
{
- return false;
- }
- return SetChopConf((configuredChopConfReg & ~CHOPCONF_TOFF_MASK) | ((newVal << CHOPCONF_TOFF_SHIFT) & CHOPCONF_TOFF_MASK));
-}
+ case SmartDriverRegister::chopperControl:
+ return configuredChopConfReg & 0x01FFFF;
-// Get microstepping or chopper control register
-uint32_t TmcDriverState::GetChopConf() const
-{
- return configuredChopConfReg & 0x01FFFF;
+ case SmartDriverRegister::toff:
+ return (configuredChopConfReg & CHOPCONF_TOFF_MASK) >> CHOPCONF_TOFF_SHIFT;
+
+ case SmartDriverRegister::tblank:
+ return (configuredChopConfReg & CHOPCONF_TBL_MASK) >> CHOPCONF_TBL_SHIFT;
+
+ case SmartDriverRegister::hstart:
+ return (configuredChopConfReg & CHOPCONF_HSTRT_MASK) >> CHOPCONF_HSTRT_SHIFT;
+
+ case SmartDriverRegister::hend:
+ return (configuredChopConfReg & CHOPCONF_HEND_MASK) >> CHOPCONF_HEND_SHIFT;
+
+ case SmartDriverRegister::tpwmthrs:
+ return writeRegisters[WriteTpwmthrs];
+
+ case SmartDriverRegister::hdec:
+ case SmartDriverRegister::coolStep:
+ default:
+ return 0;
+ }
}
-// Get the off time from the chopper control register
-uint32_t TmcDriverState::GetOffTime() const
+// Set the chopper control register to the settings provided by the user. We allow only the lowest 17 bits to be set.
+bool TmcDriverState::SetChopConf(uint32_t newVal)
{
- return (configuredChopConfReg & CHOPCONF_TOFF_MASK) >> CHOPCONF_TOFF_SHIFT;
+ const uint32_t offTime = (newVal & CHOPCONF_TOFF_MASK) >> CHOPCONF_TOFF_SHIFT;
+ if (offTime == 0 || (offTime == 1 && (newVal & CHOPCONF_TBL_MASK) < (2 << CHOPCONF_TBL_SHIFT)))
+ {
+ return false;
+ }
+ const uint32_t hstrt = (newVal & CHOPCONF_HSTRT_MASK) >> CHOPCONF_HSTRT_SHIFT;
+ const uint32_t hend = (newVal & CHOPCONF_HEND_MASK) >> CHOPCONF_HEND_SHIFT;
+ if (hstrt + hend > 16)
+ {
+ return false;
+ }
+ const uint32_t userMask = CHOPCONF_TBL_MASK | CHOPCONF_HSTRT_MASK | CHOPCONF_HEND_MASK | CHOPCONF_TOFF_MASK; // mask of bits the user is allowed to change
+ configuredChopConfReg = (configuredChopConfReg & ~userMask) | (newVal & userMask);
+ UpdateChopConfRegister();
+ return true;
}
// Set the driver mode
@@ -1002,26 +1050,6 @@ namespace SmartDrivers
return (driver < numTmc22xxDrivers) ? driverStates[driver].GetDriverMode() : DriverMode::unknown;
}
- bool SetChopperControlRegister(size_t driver, uint32_t ccr)
- {
- return driver < numTmc22xxDrivers && driverStates[driver].SetChopConf(ccr);
- }
-
- uint32_t GetChopperControlRegister(size_t driver)
- {
- return (driver < numTmc22xxDrivers) ? driverStates[driver].GetChopConf() : 0;
- }
-
- bool SetOffTime(size_t driver, uint32_t offTime)
- {
- return driver < numTmc22xxDrivers && driverStates[driver].SetOffTime(offTime);
- }
-
- uint32_t GetOffTime(size_t driver)
- {
- return (driver < numTmc22xxDrivers) ? driverStates[driver].GetOffTime() : 0;
- }
-
// Flag that the the drivers have been powered up or down and handle any timeouts
// Before the first call to this function with 'powered' true, you must call Init()
void Spin(bool powered)
@@ -1107,11 +1135,6 @@ namespace SmartDrivers
// We don't use it with TMC22xx drivers.
}
- void SetCoolStep(size_t drive, uint16_t coolStepConfig)
- {
- // Not supported on the TMC22xx
- }
-
void AppendDriverStatus(size_t drive, const StringRef& reply)
{
if (drive < numTmc22xxDrivers)
@@ -1131,7 +1154,16 @@ namespace SmartDrivers
{
driverStates[drive].SetStandstillCurrentPercent(percent);
}
+ }
+ bool SetRegister(size_t driver, SmartDriverRegister reg, uint32_t regVal)
+ {
+ return (driver < numTmc22xxDrivers) && driverStates[driver].SetRegister(reg, regVal);
+ }
+
+ uint32_t GetRegister(size_t driver, SmartDriverRegister reg)
+ {
+ return (driver < numTmc22xxDrivers) ? driverStates[driver].GetRegister(reg) : 0;
}
}; // end namespace
diff --git a/src/Movement/StepperDrivers/TMC22xx.h b/src/Movement/StepperDrivers/TMC22xx.h
index 7aed6ca2..38e3261d 100644
--- a/src/Movement/StepperDrivers/TMC22xx.h
+++ b/src/Movement/StepperDrivers/TMC22xx.h
@@ -17,7 +17,7 @@
#endif
#include "RepRapFirmware.h"
-#include "GCodes/DriverMode.h"
+#include "DriverMode.h"
#include "Pins.h"
#include "MessageType.h"
#include "Libraries/General/StringRef.h"
@@ -48,16 +48,13 @@ namespace SmartDrivers
unsigned int GetMicrostepping(size_t drive, bool& interpolation);
bool SetDriverMode(size_t driver, unsigned int mode);
DriverMode GetDriverMode(size_t driver);
- bool SetChopperControlRegister(size_t driver, uint32_t ccr);
- uint32_t GetChopperControlRegister(size_t driver);
- bool SetOffTime(size_t driver, uint32_t ccr);
- uint32_t GetOffTime(size_t driver);
void Spin(bool powered);
void TurnDriversOff();
- void SetCoolStep(size_t drive, uint16_t coolStepConfig);
void AppendDriverStatus(size_t drive, const StringRef& reply);
float GetStandstillCurrentPercent(size_t drive);
void SetStandstillCurrentPercent(size_t drive, float percent);
+ bool SetRegister(size_t driver, SmartDriverRegister reg, uint32_t regVal);
+ uint32_t GetRegister(size_t driver, SmartDriverRegister reg);
};
#endif
diff --git a/src/Movement/StepperDrivers/TMC2660.cpp b/src/Movement/StepperDrivers/TMC2660.cpp
index 4c439f9e..62737fae 100644
--- a/src/Movement/StepperDrivers/TMC2660.cpp
+++ b/src/Movement/StepperDrivers/TMC2660.cpp
@@ -77,14 +77,20 @@ const uint32_t TMC_DRVCONF_TST = 1 << 16;
// Chopper control register bits
const uint32_t TMC_CHOPCONF_TOFF_MASK = 15;
const uint32_t TMC_CHOPCONF_TOFF_SHIFT = 0;
-#define TMC_CHOPCONF_TOFF(n) ((((uint32_t)n) & 15) << 0)
-#define TMC_CHOPCONF_HSTRT(n) ((((uint32_t)n) & 7) << 4)
-#define TMC_CHOPCONF_HEND(n) ((((uint32_t)n) & 15) << 7)
-#define TMC_CHOPCONF_HDEC(n) ((((uint32_t)n) & 3) << 11)
+const uint32_t TMC_CHOPCONF_HSTRT_MASK = (7 << 4);
+const uint32_t TMC_CHOPCONF_HSTRT_SHIFT = 4;
+const uint32_t TMC_CHOPCONF_HEND_MASK = (15 << 7);
+const uint32_t TMC_CHOPCONF_HEND_SHIFT = 7;
+const uint32_t TMC_CHOPCONF_HDEC_MASK = (3 << 11);
+const uint32_t TMC_CHOPCONF_HDEC_SHIFT = 11;
const uint32_t TMC_CHOPCONF_RNDTF = 1 << 13;
const uint32_t TMC_CHOPCONF_CHM = 1 << 14;
const uint32_t TMC_CHOPCONF_TBL_MASK = (3 << 15);
const uint32_t TMC_CHOPCONF_TBL_SHIFT = 15;
+#define TMC_CHOPCONF_TOFF(n) ((((uint32_t)n) & 15) << 0)
+#define TMC_CHOPCONF_HSTRT(n) ((((uint32_t)n) & 7) << 4)
+#define TMC_CHOPCONF_HEND(n) ((((uint32_t)n) & 15) << 7)
+#define TMC_CHOPCONF_HDEC(n) ((((uint32_t)n) & 3) << 11)
#define TMC_CHOPCONF_TBL(n) (((uint32_t)n & 3) << 15)
// Driver control register bits, when SDOFF=0
@@ -169,11 +175,6 @@ public:
void SetAxisNumber(size_t p_axisNumber);
void WriteAll();
- bool SetChopConf(uint32_t newVal);
- bool SetOffTime(uint32_t newVal);
- uint32_t GetChopConf() const;
- uint32_t GetOffTime() const;
- void SetCoolStep(uint16_t coolStepConfig);
bool SetMicrostepping(uint32_t shift, bool interpolate);
unsigned int GetMicrostepping(bool& interpolation) const; // Get microstepping
bool SetDriverMode(unsigned int mode);
@@ -187,6 +188,9 @@ public:
void AppendStallConfig(const StringRef& reply) const;
void AppendDriverStatus(const StringRef& reply);
+ bool SetRegister(SmartDriverRegister reg, uint32_t regVal);
+ uint32_t GetRegister(SmartDriverRegister reg) const;
+
void TransferDone() __attribute__ ((hot)); // called by the ISR when the SPI transfer has completed
void StartTransfer() __attribute__ ((hot)); // called to start a transfer
@@ -194,6 +198,8 @@ public:
uint32_t ReadAccumulatedStatus(uint32_t bitsToKeep);
private:
+ bool SetChopConf(uint32_t newVal);
+
void ResetLoadRegisters()
{
minSgLoadRegister = 1023;
@@ -392,6 +398,70 @@ inline void TmcDriverState::WriteAll()
registersToUpdate = UpdateAllRegisters;
}
+bool TmcDriverState::SetRegister(SmartDriverRegister reg, uint32_t regVal)
+{
+ switch(reg)
+ {
+ case SmartDriverRegister::chopperControl:
+ return SetChopConf(regVal);
+
+ case SmartDriverRegister::coolStep:
+ registers[SmartEnable] = TMC_REG_SMARTEN | (regVal & 0xFFFF);
+ registersToUpdate |= 1u << SmartEnable;
+ return true;
+
+ case SmartDriverRegister::toff:
+ return SetChopConf((configuredChopConfReg & ~TMC_CHOPCONF_TOFF_MASK) | ((regVal << TMC_CHOPCONF_TOFF_SHIFT) & TMC_CHOPCONF_TOFF_MASK));
+
+ case SmartDriverRegister::tblank:
+ return SetChopConf((configuredChopConfReg & ~TMC_CHOPCONF_TBL_MASK) | ((regVal << TMC_CHOPCONF_TBL_SHIFT) & TMC_CHOPCONF_TBL_MASK));
+
+ case SmartDriverRegister::hstart:
+ return SetChopConf((configuredChopConfReg & ~TMC_CHOPCONF_HSTRT_MASK) | ((regVal << TMC_CHOPCONF_HSTRT_SHIFT) & TMC_CHOPCONF_HSTRT_MASK));
+
+ case SmartDriverRegister::hend:
+ return SetChopConf((configuredChopConfReg & ~TMC_CHOPCONF_HEND_MASK) | ((regVal << TMC_CHOPCONF_HEND_SHIFT) & TMC_CHOPCONF_HEND_MASK));
+
+ case SmartDriverRegister::hdec:
+ return SetChopConf((configuredChopConfReg & ~TMC_CHOPCONF_HDEC_MASK) | ((regVal << TMC_CHOPCONF_HDEC_SHIFT) & TMC_CHOPCONF_HDEC_MASK));
+
+ case SmartDriverRegister::tpwmthrs:
+ default:
+ return false;
+ }
+}
+
+uint32_t TmcDriverState::GetRegister(SmartDriverRegister reg) const
+{
+ switch(reg)
+ {
+ case SmartDriverRegister::chopperControl:
+ return configuredChopConfReg & TMC_DATA_MASK;
+
+ case SmartDriverRegister::coolStep:
+ return registers[SmartEnable] & TMC_DATA_MASK;
+
+ case SmartDriverRegister::toff:
+ return (configuredChopConfReg & TMC_CHOPCONF_TOFF_MASK) >> TMC_CHOPCONF_TOFF_SHIFT;
+
+ case SmartDriverRegister::tblank:
+ return (configuredChopConfReg & TMC_CHOPCONF_TBL_MASK) >> TMC_CHOPCONF_TBL_SHIFT;
+
+ case SmartDriverRegister::hstart:
+ return (configuredChopConfReg & TMC_CHOPCONF_HSTRT_MASK) >> TMC_CHOPCONF_HSTRT_SHIFT;
+
+ case SmartDriverRegister::hend:
+ return (configuredChopConfReg & TMC_CHOPCONF_HEND_MASK) >> TMC_CHOPCONF_HEND_SHIFT;
+
+ case SmartDriverRegister::hdec:
+ return (configuredChopConfReg & TMC_CHOPCONF_HDEC_MASK) >> TMC_CHOPCONF_HDEC_SHIFT;
+
+ case SmartDriverRegister::tpwmthrs:
+ default:
+ return 0;
+ }
+}
+
// Check the new chopper control register, update it and return true if it is legal
bool TmcDriverState::SetChopConf(uint32_t newVal)
{
@@ -402,21 +472,20 @@ bool TmcDriverState::SetChopConf(uint32_t newVal)
{
return false;
}
+ if ((newVal & TMC_CHOPCONF_CHM) == 0)
+ {
+ const uint32_t hstrt = (newVal & TMC_CHOPCONF_HSTRT_MASK) >> TMC_CHOPCONF_HSTRT_SHIFT;
+ const uint32_t hend = (newVal & TMC_CHOPCONF_HEND_MASK) >> TMC_CHOPCONF_HEND_SHIFT;
+ if (hstrt + hend > 15)
+ {
+ return false;
+ }
+ }
configuredChopConfReg = (newVal & 0x0001FFFF) | TMC_REG_CHOPCONF; // save the new value
UpdateChopConfRegister(); // send the new value, keeping the current Enable status
return true;
}
-// Set the off time in the chopper control register
-bool TmcDriverState::SetOffTime(uint32_t newVal)
-{
- if (newVal > 15)
- {
- return false;
- }
- return SetChopConf((configuredChopConfReg & ~TMC_CHOPCONF_TOFF_MASK) | ((newVal << TMC_CHOPCONF_TOFF_SHIFT) & TMC_CHOPCONF_TOFF_MASK));
-}
-
// Set the driver mode
bool TmcDriverState::SetDriverMode(unsigned int mode)
{
@@ -541,12 +610,6 @@ void TmcDriverState::SetStallMinimumStepsPerSecond(unsigned int stepsPerSecond)
maxStallStepInterval = StepClockRate/max<unsigned int>(stepsPerSecond, 1);
}
-void TmcDriverState::SetCoolStep(uint16_t coolStepConfig)
-{
- registers[SmartEnable] = TMC_REG_SMARTEN | coolStepConfig;
- registersToUpdate |= 1u << SmartEnable;
-}
-
void TmcDriverState::AppendStallConfig(const StringRef& reply) const
{
const bool filtered = ((registers[StallGuardConfig] & TMC_SGCSCONF_SGT_SFILT) != 0);
@@ -609,18 +672,6 @@ unsigned int TmcDriverState::GetMicrostepping(bool& interpolation) const
return 1u << microstepShiftFactor;
}
-// Get chopper control register
-uint32_t TmcDriverState::GetChopConf() const
-{
- return configuredChopConfReg & TMC_DATA_MASK;
-}
-
-// Get the off time from the chopper control register
-uint32_t TmcDriverState::GetOffTime() const
-{
- return (configuredChopConfReg & TMC_CHOPCONF_TOFF_MASK) >> TMC_CHOPCONF_TOFF_SHIFT;
-}
-
// This is called by the ISR when the SPI transfer has completed
inline void TmcDriverState::TransferDone()
{
@@ -896,26 +947,6 @@ namespace SmartDrivers
return (driver < numTmc2660Drivers) ? driverStates[driver].GetDriverMode() : DriverMode::unknown;
}
- bool SetChopperControlRegister(size_t driver, uint32_t ccr)
- {
- return driver < numTmc2660Drivers && driverStates[driver].SetChopConf(ccr);
- }
-
- uint32_t GetChopperControlRegister(size_t driver)
- {
- return (driver < numTmc2660Drivers) ? driverStates[driver].GetChopConf() : 0;
- }
-
- bool SetOffTime(size_t driver, uint32_t offTime)
- {
- return driver < numTmc2660Drivers && driverStates[driver].SetOffTime(offTime);
- }
-
- uint32_t GetOffTime(size_t driver)
- {
- return (driver < numTmc2660Drivers) ? driverStates[driver].GetOffTime() : 0;
- }
-
// Flag the the drivers have been powered up.
// Before the first call to this function with powered true, you must call Init().
void Spin(bool powered)
@@ -979,14 +1010,6 @@ namespace SmartDrivers
}
}
- void SetCoolStep(size_t drive, uint16_t coolStepConfig)
- {
- if (drive < numTmc2660Drivers)
- {
- driverStates[drive].SetCoolStep(coolStepConfig);
- }
- }
-
void AppendStallConfig(size_t driver, const StringRef& reply)
{
if (driver < numTmc2660Drivers)
@@ -1013,6 +1036,16 @@ namespace SmartDrivers
// not supported so nothing to see here
}
+ bool SetRegister(size_t driver, SmartDriverRegister reg, uint32_t regVal)
+ {
+ return (driver < numTmc2660Drivers) && driverStates[driver].SetRegister(reg, regVal);
+ }
+
+ uint32_t GetRegister(size_t driver, SmartDriverRegister reg)
+ {
+ return (driver < numTmc2660Drivers) ? driverStates[driver].GetRegister(reg) : 0;
+ }
+
}; // end namespace
#endif
diff --git a/src/Movement/StepperDrivers/TMC2660.h b/src/Movement/StepperDrivers/TMC2660.h
index a94aedcb..e10795a4 100644
--- a/src/Movement/StepperDrivers/TMC2660.h
+++ b/src/Movement/StepperDrivers/TMC2660.h
@@ -11,7 +11,7 @@
#if SUPPORT_TMC2660
#include "RepRapFirmware.h"
-#include "GCodes/DriverMode.h"
+#include "DriverMode.h"
#include "Pins.h"
#include "MessageType.h"
#include "Libraries/General/StringRef.h"
@@ -42,18 +42,15 @@ namespace SmartDrivers
unsigned int GetMicrostepping(size_t drive, bool& interpolation);
bool SetDriverMode(size_t driver, unsigned int mode);
DriverMode GetDriverMode(size_t driver);
- bool SetChopperControlRegister(size_t driver, uint32_t ccr);
- uint32_t GetChopperControlRegister(size_t driver);
- bool SetOffTime(size_t driver, uint32_t ccr);
- uint32_t GetOffTime(size_t driver);
void SetStallThreshold(size_t driver, int sgThreshold);
void SetStallFilter(size_t driver, bool sgFilter);
void SetStallMinimumStepsPerSecond(size_t driver, unsigned int stepsPerSecond);
- void SetCoolStep(size_t driver, uint16_t coolStepConfig);
void AppendStallConfig(size_t driver, const StringRef& reply);
void AppendDriverStatus(size_t driver, const StringRef& reply);
float GetStandstillCurrentPercent(size_t driver);
void SetStandstillCurrentPercent(size_t driver, float percent);
+ bool SetRegister(size_t driver, SmartDriverRegister reg, uint32_t regVal);
+ uint32_t GetRegister(size_t driver, SmartDriverRegister reg);
};
#endif
diff --git a/src/Movement/StepperDrivers/TMC51xx.cpp b/src/Movement/StepperDrivers/TMC51xx.cpp
index 2c5efd18..07c88bc0 100644
--- a/src/Movement/StepperDrivers/TMC51xx.cpp
+++ b/src/Movement/StepperDrivers/TMC51xx.cpp
@@ -196,11 +196,6 @@ public:
void Init(uint32_t p_driverNumber, Pin p_pin);
void SetAxisNumber(size_t p_axisNumber);
void WriteAll();
- bool SetChopConf(uint32_t newVal);
- bool SetOffTime(uint32_t newVal);
- uint32_t GetChopConf() const;
- uint32_t GetOffTime() const;
- void SetCoolStep(uint16_t coolStepConfig);
bool SetMicrostepping(uint32_t shift, bool interpolate);
unsigned int GetMicrostepping(bool& interpolation) const; // Get microstepping
bool SetDriverMode(unsigned int mode);
@@ -215,6 +210,9 @@ public:
void SetStallMinimumStepsPerSecond(unsigned int stepsPerSecond);
void AppendStallConfig(const StringRef& reply) const;
+ bool SetRegister(SmartDriverRegister reg, uint32_t regVal);
+ uint32_t GetRegister(SmartDriverRegister reg) const;
+
float GetStandstillCurrentPercent() const;
void SetStandstillCurrentPercent(float percent);
@@ -246,7 +244,7 @@ private:
void SetupDMAReceive(uint8_t regnum, uint8_t crc) __attribute__ ((hot)); // set up the PDC to receive a register
#endif
- static constexpr unsigned int NumWriteRegisters = 5; // the number of registers that we write to
+ static constexpr unsigned int NumWriteRegisters = 6; // the number of registers that we write to
static const uint8_t WriteRegNumbers[NumWriteRegisters]; // the register numbers that we write to
// Write register numbers are in priority order, most urgent first, in same order as WriteRegNumbers
@@ -255,6 +253,7 @@ private:
static constexpr unsigned int WriteChopConf = 2; // enable/disable and microstep setting
static constexpr unsigned int WriteIholdIrun = 3; // current setting
static constexpr unsigned int WritePwmConf = 4; // read register select, sense voltage high/low sensitivity
+ static constexpr unsigned int WriteTpwmthrs = 5; // upper step rate limit for stealthchop
static constexpr unsigned int NumReadRegisters = 2; // the number of registers that we read from
static const uint8_t ReadRegNumbers[NumReadRegisters]; // the register numbers that we read from
@@ -447,26 +446,6 @@ namespace SmartDrivers
return (driver < numTmc51xxDrivers) ? driverStates[driver].GetDriverMode() : DriverMode::unknown;
}
- bool SetChopperControlRegister(size_t driver, uint32_t ccr)
- {
- return driver < numTmc51xxDrivers && driverStates[driver].SetChopConf(ccr);
- }
-
- uint32_t GetChopperControlRegister(size_t driver)
- {
- return (driver < numTmc51xxDrivers) ? driverStates[driver].GetChopConf() : 0;
- }
-
- bool SetOffTime(size_t driver, uint32_t offTime)
- {
- return driver < numTmc51xxDrivers && driverStates[driver].SetOffTime(offTime);
- }
-
- uint32_t GetOffTime(size_t driver)
- {
- return (driver < numTmc51xxDrivers) ? driverStates[driver].GetOffTime() : 0;
- }
-
// Flag that the the drivers have been powered up or down and handle any timeouts
// Before the first call to this function with 'powered' true, you must call Init()
void Spin(bool powered)
@@ -577,14 +556,6 @@ namespace SmartDrivers
}
}
- void SetCoolStep(size_t drive, uint16_t coolStepConfig)
- {
- if (drive < numTmc51xxDrivers)
- {
- driverStates[drive].SetCoolStep(coolStepConfig);
- }
- }
-
void AppendStallConfig(size_t driver, const StringRef& reply)
{
if (driver < numTmc51xxDrivers)
@@ -611,7 +582,18 @@ namespace SmartDrivers
// not supported so nothing to see here
}
+ bool SetRegister(size_t driver, SmartDriverRegister reg, uint32_t regVal)
+ {
+ return (driver < numTmc22xxDrivers) && driverStates[driver].SetRegister(reg, regVal);
+ }
+
+ uint32_t GetRegister(size_t driver, SmartDriverRegister reg)
+ {
+ return (driver < numTmc22xxDrivers) ? driverStates[driver].GetRegister(reg) : 0;
+ }
+
}; // end namespace
+
#endif
// End
diff --git a/src/Movement/StepperDrivers/TMC51xx.h b/src/Movement/StepperDrivers/TMC51xx.h
index 587a73cf..a9c215ff 100644
--- a/src/Movement/StepperDrivers/TMC51xx.h
+++ b/src/Movement/StepperDrivers/TMC51xx.h
@@ -41,18 +41,15 @@ namespace SmartDrivers
unsigned int GetMicrostepping(size_t drive, bool& interpolation);
bool SetDriverMode(size_t driver, unsigned int mode);
DriverMode GetDriverMode(size_t driver);
- bool SetChopperControlRegister(size_t driver, uint32_t ccr);
- uint32_t GetChopperControlRegister(size_t driver);
- bool SetOffTime(size_t driver, uint32_t ccr);
- uint32_t GetOffTime(size_t driver);
void SetStallThreshold(size_t driver, int sgThreshold);
void SetStallFilter(size_t driver, bool sgFilter);
void SetStallMinimumStepsPerSecond(size_t driver, unsigned int stepsPerSecond);
- void SetCoolStep(size_t driver, uint16_t coolStepConfig);
void AppendStallConfig(size_t driver, const StringRef& reply);
void AppendDriverStatus(size_t driver, const StringRef& reply);
float GetStandstillCurrentPercent(size_t driver);
void SetStandstillCurrentPercent(size_t driver, float percent);
+ bool SetRegister(size_t driver, SmartDriverRegister reg, uint32_t regVal);
+ uint32_t GetRegister(size_t driver, SmartDriverRegister reg);
};
#endif
diff --git a/src/NamedEnum.h b/src/NamedEnum.h
new file mode 100644
index 00000000..0f322926
--- /dev/null
+++ b/src/NamedEnum.h
@@ -0,0 +1,53 @@
+/*
+ * NamedEnum.h
+ *
+ * Created on: 27 Aug 2018
+ * Author: David
+ */
+
+#ifndef SRC_NAMEDENUM_H_
+#define SRC_NAMEDENUM_H_
+
+// Plumbing to allow overloaded STRINGLIST macro
+#define CAT( A, B ) A ## B
+#define SELECT( NAME, NUM ) CAT( NAME ## _, NUM )
+#define GET_COUNT( _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, COUNT, ... ) COUNT
+#define VA_SIZE( ... ) GET_COUNT( __VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 )
+#define VA_SELECT( NAME, ... ) SELECT( NAME, VA_SIZE(__VA_ARGS__) )(__VA_ARGS__)
+
+// Macro to turn a list of names into a list of strings
+#define STRINGLIST( ... ) VA_SELECT( STRINGLIST, __VA_ARGS__ )
+#define STRINGLIST_2(_v1,_v2) #_v1,#_v2
+#define STRINGLIST_3(_v1,_v2,_v3) #_v1,#_v2,#_v3
+#define STRINGLIST_4(_v1,_v2,_v3,_v4) #_v1,#_v2,#_v3,#_v4
+#define STRINGLIST_5(_v1,_v2,_v3,_v4,_v5) #_v1,#_v2,#_v3,#_v4,_v5
+
+// Macro to declare an enumeration with printable value names
+// Usage example:
+// NamedEnum(MakeOfCar, ford, vauxhall, bmw);
+// MakeOfCar mycar(MakeOfCar::bmw);
+// myCar = MakeOfCar::ford;
+// if (myCar == MakeOfCar::vauxhall) { ... }
+// printf("%s", myCar.ToString());
+#define NamedEnum(_typename, _v1, ...) \
+class _typename { \
+public: \
+ enum _E : unsigned int { _v1 = 0, __VA_ARGS__ }; /* underlying enumeration */ \
+ static constexpr unsigned int NumValues = VA_SIZE(__VA_ARGS__) + 1; /* count of members */ \
+ explicit _typename(_E arg) { v = arg; } /* constructor */ \
+ _typename(const _typename& arg) { v = arg.v; } /* copy constructor */ \
+ bool operator==(_typename arg) const { return v == arg.v; } /* equality operator */ \
+ bool operator!=(_typename arg) const { return v != arg.v; } /* inequality operator */ \
+ bool operator==(_E arg) const { return v == arg; } /* equality operator */ \
+ bool operator!=(_E arg) const { return v != arg; } /* inequality operator */ \
+ const _typename& operator=(_E arg) { v = arg; return *this; } /* assignment operator from underlying enum */ \
+ const _typename& operator=(_typename arg) { v = arg.v; return *this; } /* copy assignment operator */ \
+ unsigned int ToInt() const { return static_cast<unsigned int>(v); } /* conversion to unsigned integer */ \
+ const char* ToString() const { return (v < NumValues) ? _names[v] : "undefined"; } /* conversion to C string */ \
+ void Assign(unsigned int arg) { v = static_cast<_E>(arg); } /* assignment from integer */ \
+private: \
+ _E v; \
+ static constexpr const char* _names[NumValues] = { STRINGLIST(_v1, __VA_ARGS__) }; \
+}
+
+#endif /* SRC_NAMEDENUM_H_ */
diff --git a/src/ObjectModel/ObjectModel.cpp b/src/ObjectModel/ObjectModel.cpp
new file mode 100644
index 00000000..a278a219
--- /dev/null
+++ b/src/ObjectModel/ObjectModel.cpp
@@ -0,0 +1,308 @@
+/*
+ * ObjectModel.cpp
+ *
+ * Created on: 27 Aug 2018
+ * Author: David
+ */
+
+#include "ObjectModel.h"
+
+#ifdef SUPPORT_OBJECT_MODEL
+
+#include "OutputMemory.h"
+#include <cstring>
+
+// Constructor
+ObjectModel::ObjectModel()
+{
+}
+
+// Report this object
+bool ObjectModel::ReportAsJson(OutputBuffer* buf, const char* filter, ReportFlags flags)
+{
+ size_t numEntries;
+ const ObjectModelTableEntry *tbl = GetObjectModelTable(numEntries);
+ const char *moduleName = GetModuleName();
+ if (moduleName != nullptr) // if we are not the root object
+ {
+ buf->cat(moduleName);
+ buf->cat(':');
+ filter = GetNextElement(filter); // skip the bit that matches the name of this module
+ }
+
+ buf->cat('{');
+ bool added = false;
+ while (numEntries != 0)
+ {
+ if (added)
+ {
+ buf->cat(',');
+ }
+ if (filter[0] == 0 || tbl->Matches(filter, flags))
+ {
+ tbl->ReportAsJson(buf, this, filter, flags);
+ added = true;
+ }
+ --numEntries;
+ ++tbl;
+ }
+ buf->cat('}');
+ return true;
+}
+
+// Find the requested entry
+const ObjectModelTableEntry* ObjectModel::FindObjectModelTableEntry(const char* idString)
+{
+ size_t numElems;
+ const ObjectModelTableEntry *tbl = GetObjectModelTable(numElems);
+ size_t low = 0, high = numElems;
+ while (high > low)
+ {
+ const size_t mid = (high - low)/2 + low;
+ const int t = tbl[mid].IdCompare(idString);
+ if (t == 0)
+ {
+ return &tbl[mid];
+ }
+ if (t > 0)
+ {
+ low = mid + 1u;
+ }
+ else
+ {
+ high = mid;
+ }
+ }
+ return (low < numElems && tbl[low].IdCompare(idString) == 0) ? &tbl[low] : nullptr;
+}
+
+// Get the object model table entry for the leaf object in the query
+const ObjectModelTableEntry *ObjectModel::FindObjectModelLeafEntry(const char *idString)
+{
+ const ObjectModelTableEntry *e = FindObjectModelTableEntry(idString);
+ return (e == nullptr) ? e : e->FindLeafEntry(this, idString);
+}
+
+#if 0 // not implemented yet
+bool ObjectModel::GetStringObjectValue(const StringRef& str, const char* idString) const
+{
+}
+
+bool ObjectModel::GetLongEnumObjectValue(const StringRef& str, const char* idString) const
+{
+}
+
+bool ObjectModel::GetShortEnumObjectValue(uint32_t& val, const char* idString) const
+{
+}
+
+bool ObjectModel::GetBitmapObjectValue(uint32_t& val, const char* idString) const
+{
+}
+#endif
+
+#if 0
+bool ObjectModel::SetFloatObjectValue(float val, const char* idString)
+{
+}
+
+bool ObjectModel::SetUnsignedObjectValue(uint32_t val, const char* idString)
+{
+}
+
+bool ObjectModel::SetSignedObjectValue(int32_t val, const char* idString)
+{
+}
+
+bool ObjectModel::SetStringObjectValue(const StringRef& str, const char* idString)
+{
+}
+
+bool ObjectModel::SetLongEnumObjectValue(const StringRef& str, const char* idString)
+{
+}
+
+bool ObjectModel::SetShortEnumObjectValue(uint32_t val, const char* idString)
+{
+}
+
+bool ObjectModel::SetBitmapObjectValue(uint32_t val, const char* idString)
+{
+}
+
+bool ObjectModel::SetBoolObjectValue(bool val, const char* idString)
+{
+}
+
+bool ObjectModel::AdjustFloatObjectValue(float val, const char* idString)
+{
+}
+
+bool ObjectModel::AdjustUnsignedObjectValue(int32_t val, const char* idString)
+{
+}
+
+bool ObjectModel::AdjustSignedObjectValue(int32_t val, const char* idString)
+{
+}
+
+bool ObjectModel::ToggleBoolObjectValue(const char* idString)
+{
+}
+#endif
+
+const char** ObjectModel::GetStringObjectPointer(const char* idString)
+{
+ //TODO
+ return nullptr;
+}
+
+uint32_t* ObjectModel::GetShortEnumObjectPointer(const char* idString)
+{
+ const ObjectModelTableEntry *e = FindObjectModelLeafEntry(idString);
+ return (e == nullptr) ? nullptr : (uint32_t*)(e->GetValuePointer(this, TYPE_OF(Enum32)));
+}
+
+uint32_t* ObjectModel::GetBitmapObjectPointer(const char* idString)
+{
+ const ObjectModelTableEntry *e = FindObjectModelLeafEntry(idString);
+ return (e == nullptr) ? nullptr : (uint32_t*)(e->GetValuePointer(this, TYPE_OF(Bitmap32)));
+}
+
+/*static*/ const char* ObjectModel::GetNextElement(const char *id)
+{
+ while (*id != 0 && *id != '.' && *id != '[')
+ {
+ ++id;
+ }
+ if (*id == '.')
+ {
+ ++id;
+ }
+ return id;
+}
+
+bool ObjectModelTableEntry::Matches(const char* filterString, ObjectModelFilterFlags filterFlags) const
+{
+ return IdCompare(filterString) == 0 && (flags & filterFlags) == filterFlags;
+}
+
+const ObjectModelTableEntry *ObjectModelTableEntry::FindLeafEntry(ObjectModel *self, const char *idString) const
+{
+ if (!IsObject())
+ {
+ return this;
+ }
+
+ return ((ObjectModel*)param(self))->FindObjectModelLeafEntry(ObjectModel::GetNextElement(idString));
+}
+
+// Add the value of this element to the buffer, returning true if it matched and we did
+bool ObjectModelTableEntry::ReportAsJson(OutputBuffer* buf, ObjectModel *self, const char* filter, ObjectModel::ReportFlags flags) const
+{
+ //TODO handle arrays
+ buf->cat(name);
+ buf->cat(':');
+
+ if ((type & isArray) != 0)
+ {
+ //TODO
+ buf->cat("[]");
+ }
+ else
+ {
+ void *nParam = param(self);
+ switch (type & 15)
+ {
+ case TYPE_OF(ObjectModel):
+ ((ObjectModel*)nParam)->ReportAsJson(buf, filter, flags);
+ break;
+
+ case TYPE_OF(float):
+ buf->cat("%.1f", (double)*(const float *)nParam); //TODO different parameters need different number of decimal places
+ break;
+
+ case TYPE_OF(uint32_t):
+ buf->cat("%" PRIu32, *(const uint32_t *)nParam);
+ break;
+
+ case TYPE_OF(int32_t):
+ buf->cat("%" PRIi32, *(const int32_t *)nParam);
+ break;
+
+ case TYPE_OF(Bitmap32):
+ if (flags & ObjectModel::shortForm)
+ {
+ buf->cat("%" PRIu32, *(const uint32_t *)nParam);
+ }
+ else
+ {
+ buf->cat('[');
+ // TODO list the bits that are set
+ buf->cat(']');
+ }
+ break;
+
+ case TYPE_OF(Enum32):
+ if (flags & ObjectModel::shortForm)
+ {
+ buf->cat("%" PRIu32, *(const uint32_t *)nParam);
+ }
+ else
+ {
+ buf->cat("\"unimplemented\"");
+ // TODO append the real name
+ }
+ break;
+
+ case TYPE_OF(bool):
+ {
+ const bool bVal = *(const bool *)nParam;
+ if (flags & ObjectModel::shortForm)
+ {
+ buf->cat((bVal) ? '1' : '0');
+ }
+ else
+ {
+ buf->cat((bVal) ? "yes" : "no");
+ }
+ }
+ break;
+ }
+ }
+
+ return true;
+}
+
+// Compare and ID with the name of this object
+int ObjectModelTableEntry::IdCompare(const char *id) const
+{
+ if (id[0] == '*')
+ {
+ return true;
+ }
+
+ const char *n = name;
+ while (*id == *n && *n != 0)
+ {
+ ++id;
+ ++n;
+ }
+ return (*n == 0 && (*id == 0 || *id == '.' || *id == '[')) ? 0
+ : (*id > *n) ? 1
+ : -1;
+}
+
+// Check the type is correct, call the function if necessary and return the pointer
+void* ObjectModelTableEntry::GetValuePointer(ObjectModel *self, TypeCode t) const
+{
+ if (t != type)
+ {
+ return nullptr;
+ }
+ return param(self);
+}
+
+#endif
+
+// End
diff --git a/src/ObjectModel/ObjectModel.h b/src/ObjectModel/ObjectModel.h
new file mode 100644
index 00000000..dddc6e21
--- /dev/null
+++ b/src/ObjectModel/ObjectModel.h
@@ -0,0 +1,160 @@
+/*
+ * ObjectModel.h
+ *
+ * Created on: 27 Aug 2018
+ * Author: David
+ */
+
+#ifndef SRC_OBJECTMODEL_OBJECTMODEL_H_
+#define SRC_OBJECTMODEL_OBJECTMODEL_H_
+
+#include "RepRapFirmware.h"
+
+#ifdef SUPPORT_OBJECT_MODEL
+
+typedef uint32_t ObjectModelFilterFlags;
+typedef uint8_t TypeCode;
+
+// Dummy types, used to define type codes
+class Bitmap32 { };
+class Enum32 { };
+
+// Forward declarations
+class ObjectModelTableEntry;
+
+class ObjectModel
+{
+public:
+ enum ReportFlags : uint16_t
+ {
+ shortForm = 1
+ };
+
+ ObjectModel();
+
+ // Construct a JSON representation of those parts of the object model requested by the user
+ bool ReportAsJson(OutputBuffer *buf, const char *filter, ReportFlags rflags);
+
+ // Get values of various types from the object model, returning true if successful
+ template<class T> bool GetObjectValue(T& val, const char *idString);
+
+ bool GetStringObjectValue(const StringRef& str, const char* idString) const;
+ bool GetLongEnumObjectValue(const StringRef& str, const char *idString) const;
+ bool GetShortEnumObjectValue(uint32_t &val, const char *idString) const;
+ bool GetBitmapObjectValue(uint32_t &val, const char *idString) const;
+
+ // Try to set values of various types from the object model, returning true if successful
+ bool SetFloatObjectValue(float val, const char *idString);
+ bool SetUnsignedObjectValue(uint32_t val, const char *idString);
+ bool SetSignedObjectValue(int32_t val, const char *idString);
+ bool SetStringObjectValue(const StringRef& str, const char *idString);
+ bool SetLongEnumObjectValue(const StringRef& str, const char *idString);
+ bool SetShortEnumObjectValue(uint32_t val, const char *idString);
+ bool SetBitmapObjectValue(uint32_t val, const char *idString);
+ bool SetBoolObjectValue(bool val, const char *idString);
+
+ // Try to adjust values of various types from the object model, returning true if successful
+ bool AdjustFloatObjectValue(float val, const char *idString);
+ bool AdjustUnsignedObjectValue(int32_t val, const char *idString);
+ bool AdjustSignedObjectValue(int32_t val, const char *idString);
+ bool ToggleBoolObjectValue(const char *idString);
+
+ // Get the object model table entry for the current level object in the query
+ const ObjectModelTableEntry *FindObjectModelTableEntry(const char *idString);
+
+ // Get the object model table entry for the leaf object in the query
+ const ObjectModelTableEntry *FindObjectModelLeafEntry(const char *idString);
+ // Skip the current element in the ID or filter string
+ static const char* GetNextElement(const char *id);
+
+protected:
+ virtual const char *GetModuleName() const = 0;
+ virtual const ObjectModelTableEntry *GetObjectModelTable(size_t& numEntries) const = 0;
+
+private:
+ // Get pointers to various types from the object model, returning null if failed
+ template<class T> T* GetObjectPointer(const char* idString);
+
+ const char **GetStringObjectPointer(const char *idString);
+ uint32_t *GetShortEnumObjectPointer(const char *idString);
+ uint32_t *GetBitmapObjectPointer(const char *idString);
+};
+
+// Function template used to get constexpr type IDs
+template<class T> constexpr TypeCode TypeOf();
+
+template<> constexpr TypeCode TypeOf<bool> () { return 1; }
+template<> constexpr TypeCode TypeOf<uint32_t> () { return 2; }
+template<> constexpr TypeCode TypeOf<int32_t>() { return 3; }
+template<> constexpr TypeCode TypeOf<float>() { return 4; }
+template<> constexpr TypeCode TypeOf<Bitmap32>() { return 5; }
+template<> constexpr TypeCode TypeOf<Enum32>() { return 6; }
+template<> constexpr TypeCode TypeOf<ObjectModel>() { return 7; }
+
+#define TYPE_OF(_t) (TypeOf<_t>())
+
+// Object model table entry
+// It must be possible to construct these in the form of initialised data in flash memory, to avoid using large amounts of RAM.
+// Therefore we can't use a class hierarchy to represent different types of entry. Instead we use a type code and a void* parameter.
+// Only const member functions are allowed in this class
+class ObjectModelTableEntry
+{
+public:
+ enum ObjectModelEntryFlags : uint16_t
+ {
+ none = 0,
+ live = 1, // fast changing data, included in common status response
+ canAlter = 2, // we can alter this value
+ isArray = 4 // value is an array of the basic type
+ };
+
+ typedef void *(*ParamFuncPtr_t)(ObjectModel*);
+
+ // Return true if this object table entry matches a filter or query
+ bool Matches(const char *filter, ObjectModelFilterFlags flags) const;
+
+ // Add the value of this element to the buffer, returning true if it matched and we did
+ bool ReportAsJson(OutputBuffer* buf, ObjectModel *self, const char* filter, ObjectModel::ReportFlags flags) const;
+
+ const char* GetName() const { return name; }
+
+ int IdCompare(const char *id) const;
+
+ bool IsObject() const { return type == TYPE_OF(ObjectModel); }
+ const ObjectModelTableEntry *FindLeafEntry(ObjectModel *self, const char *idString) const;
+
+ // Check the type is correct, call the function if necessary and return the pointer
+ void* GetValuePointer(ObjectModel *self, TypeCode t) const;
+
+ // Note: all data members must be public so that we can brace-initialise these. This doesn't matter because they are always 'const'.
+ const char * name;
+ ParamFuncPtr_t param;
+ TypeCode type;
+ ObjectModelEntryFlags flags;
+};
+
+template<class T> bool ObjectModel::GetObjectValue(T& val, const char *idString)
+{
+ const ObjectModelTableEntry *e = FindObjectModelLeafEntry(idString);
+ if (e == nullptr)
+ {
+ return false;
+ }
+ const T *p = (float*)(e->GetValuePointer(this, TYPE_OF(T)));
+ if (p == nullptr)
+ {
+ return false;
+ }
+ val = *p;
+ return true;
+}
+
+template<class T> T* ObjectModel::GetObjectPointer(const char* idString)
+{
+ const ObjectModelTableEntry *e = FindObjectModelLeafEntry(idString);
+ return (e == nullptr) ? nullptr : (T*)(e->GetValuePointer(this, TYPE_OF(T)));
+}
+
+#endif
+
+#endif /* SRC_OBJECTMODEL_OBJECTMODEL_H_ */
diff --git a/src/Platform.cpp b/src/Platform.cpp
index 2cf4eb56..eafcdc41 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -4466,7 +4466,7 @@ bool Platform::ConfigureStallDetection(GCodeBuffer& gb, const StringRef& reply)
{
if (IsBitSet(drivers, drive))
{
- SmartDrivers::SetCoolStep(drive, coolStepConfig);
+ SmartDrivers::SetRegister(drive, SmartDriverRegister::coolStep, coolStepConfig);
}
}
}
diff --git a/src/RepRap.cpp b/src/RepRap.cpp
index 76e18a59..9f28ae82 100644
--- a/src/RepRap.cpp
+++ b/src/RepRap.cpp
@@ -119,6 +119,33 @@ extern "C" void hsmciIdle(uint32_t stBits, uint32_t dmaBits)
#endif
+#ifdef SUPPORT_OBJECT_MODEL
+
+// Object model table and functions
+// Note: if using GCC version 7.3.1 20180622 then if lambda functions are used in this table, you must compile this file with option -std=gnu++17.
+// Otherwise the table will be allocate 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(_ret) [] (ObjectModel* arg) { RepRap * const self = static_cast<RepRap*>(arg); return (void *)(_ret); }
+
+const ObjectModelTableEntry RepRap::objectModelTable[] =
+{
+ { "gcodes", OBJECT_MODEL_FUNC(&(self->GetGCodes())), TYPE_OF(ObjectModel), ObjectModelTableEntry::none }
+};
+
+const char *RepRap::GetModuleName() const
+{
+ return nullptr; // this module has no name and doesn't need one
+}
+
+const ObjectModelTableEntry *RepRap::GetObjectModelTable(size_t& numEntries) const
+{
+ numEntries = ARRAY_SIZE(objectModelTable);
+ return objectModelTable;
+}
+
+#endif
+
// RepRap member functions.
// Do nothing more in the constructor; put what you want in RepRap:Init()
diff --git a/src/RepRap.h b/src/RepRap.h
index 0f741126..89e49467 100644
--- a/src/RepRap.h
+++ b/src/RepRap.h
@@ -22,6 +22,7 @@ Licence: GPL
#define REPRAP_H
#include "RepRapFirmware.h"
+#include "ObjectModel/ObjectModel.h"
#include "MessageType.h"
#include "RTOSIface.h"
@@ -33,6 +34,9 @@ enum class ResponseSource
};
class RepRap
+#ifdef SUPPORT_OBJECT_MODEL
+ : public ObjectModel
+#endif
{
public:
RepRap();
@@ -121,6 +125,14 @@ public:
void KickHeatTaskWatchdog() { heatTaskIdleTicks = 0; }
#endif
+#ifdef SUPPORT_OBJECT_MODEL
+protected:
+ const char *GetModuleName() const override;
+ const ObjectModelTableEntry *GetObjectModelTable(size_t& numEntries) const override;
+
+ static const ObjectModelTableEntry objectModelTable[];
+#endif
+
private:
static void EncodeString(StringRef& response, const char* src, size_t spaceToLeave, bool allowControlChars = false, char prefix = 0);
diff --git a/src/Version.h b/src/Version.h
index 8eba899f..ea55aaa3 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -22,7 +22,7 @@
#endif
#ifndef DATE
-# define DATE "2018-08-27b1"
+# define DATE "2018-08-29b1"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman, printm3d"