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>2016-11-05 23:00:39 +0300
committerDavid Crocker <dcrocker@eschertech.com>2016-11-05 23:01:02 +0300
commit619e5c489f7a29dc78fe900e16ee0ea5a13df4c5 (patch)
tree36d599f39034a764e17e36fc8138c8c91aec8de6 /src
parent6f71c760185f338843870b1642a540c3dce5b2c8 (diff)
Version 1.16rc2
Fixed several bugs in file time stamping Fixed M280 and M42 commands using unused heaster channels on Duet 0.6 and 0.8.5 Reduced the amount of I2C traffic, by using DueX5 interrupt line to tell if new data is available and by only sending fan PWM values when they change Display TMC2660 driver status and DueX2/X5 stall status in M122 response Removed E parameter from M574 command (use M558 I parameter instead) Fixed response to M307 with H parameter only
Diffstat (limited to 'src')
-rw-r--r--src/Configuration.h4
-rw-r--r--src/Duet/Webserver.cpp4
-rw-r--r--src/DuetNG/DueXn.cpp35
-rw-r--r--src/DuetNG/Pins_DuetNG.h1
-rw-r--r--src/DuetNG/TMC2660.cpp15
-rw-r--r--src/DuetNG/TMC2660.h9
-rw-r--r--src/DuetNG/Webserver.cpp2
-rw-r--r--src/Fan.cpp51
-rw-r--r--src/Fan.h2
-rw-r--r--src/GCodes/GCodes.cpp13
-rw-r--r--src/Libraries/Fatfs/fattime_rtc.c4
-rw-r--r--src/Platform.cpp47
-rw-r--r--src/Platform.h26
-rw-r--r--src/PrintMonitor.cpp14
-rw-r--r--src/PrintMonitor.h1
-rw-r--r--src/Reprap.cpp18
-rw-r--r--src/Storage/MassStorage.cpp55
-rw-r--r--src/Storage/MassStorage.h3
18 files changed, 209 insertions, 95 deletions
diff --git a/src/Configuration.h b/src/Configuration.h
index 9ebe291e..26982b4f 100644
--- a/src/Configuration.h
+++ b/src/Configuration.h
@@ -26,11 +26,11 @@ Licence: GPL
// Firmware name is now defined in the Pins file
#ifndef VERSION
-# define VERSION "1.16rc1"
+# define VERSION "1.16rc2"
#endif
#ifndef DATE
-# define DATE "2016-11-03"
+# define DATE "2016-11-05"
#endif
#define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman"
diff --git a/src/Duet/Webserver.cpp b/src/Duet/Webserver.cpp
index 15c21edc..8db33a5e 100644
--- a/src/Duet/Webserver.cpp
+++ b/src/Duet/Webserver.cpp
@@ -964,6 +964,7 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff
if (numQualKeys > 1 && StringEquals(qualifiers[1].key, "time") && !platform->IsDateTimeSet())
{
struct tm timeInfo;
+ memset(&timeInfo, 0, sizeof(timeInfo));
if (strptime(qualifiers[1].value, "%Y-%m-%dT%H:%M:%S", &timeInfo) != nullptr)
{
time_t newTime = mktime(&timeInfo);
@@ -1589,6 +1590,7 @@ bool Webserver::HttpInterpreter::ProcessMessage()
if (numQualKeys > 1 && StringEquals(qualifiers[1].key, "time"))
{
struct tm timeInfo;
+ memset(&timeInfo, 0, sizeof(timeInfo));
if (strptime(qualifiers[1].value, "%Y-%m-%dT%H:%M:%S", &timeInfo) != nullptr)
{
fileLastModified = mktime(&timeInfo);
@@ -2333,7 +2335,7 @@ void Webserver::FtpInterpreter::ProcessLine()
// Example for a typical UNIX-like file list:
// "drwxr-xr-x 2 ftp ftp 0 Apr 11 2013 bin\r\n"
const char dirChar = (fileInfo.isDirectory) ? 'd' : '-';
- struct tm *timeInfo = localtime(&fileInfo.lastModified);
+ const struct tm * const timeInfo = gmtime(&fileInfo.lastModified);
dataTransaction->Printf("%crw-rw-rw- 1 ftp ftp %13lu %s %02d %04d %s\r\n",
dirChar, fileInfo.size, platform->GetMassStorage()->GetMonthName(timeInfo->tm_mon + 1),
timeInfo->tm_mday, timeInfo->tm_year + 1900, fileInfo.fileName);
diff --git a/src/DuetNG/DueXn.cpp b/src/DuetNG/DueXn.cpp
index a0f1c11b..ac6f0785 100644
--- a/src/DuetNG/DueXn.cpp
+++ b/src/DuetNG/DueXn.cpp
@@ -7,12 +7,14 @@
#include "DueXn.h"
#include "SX1509.h"
+#include "Platform.h"
namespace DuetExpansion
{
static SX1509 expander;
static uint16_t inputMask;
static ExpansionBoardType boardType = ExpansionBoardType::none;
+ static uint16_t inputBits;
const uint8_t DueXnAddress = 0x3E; // address of the SX1509B on the DueX0/DueX2/DueX5
@@ -33,7 +35,8 @@ namespace DuetExpansion
const unsigned int E4StopBit = 2;
const unsigned int E5StopBit = 1;
const unsigned int E6StopBit = 13;
- const uint16_t AllStopBits = (1u << E2StopBit) | (1u << E3StopBit) | (1u << E4StopBit) | (1u << E5StopBit) | (1u << E6StopBit);
+ const uint16_t AllStopBitsX2 = (1u << E2StopBit) | (1u << E3StopBit);
+ const uint16_t AllStopBitsX5 = AllStopBitsX2 | (1u << E4StopBit) | (1u << E5StopBit) | (1u << E6StopBit);
const unsigned int Gpio1Bit = 11;
const unsigned int Gpio2Bit = 10;
@@ -64,16 +67,21 @@ namespace DuetExpansion
if (boardType != ExpansionBoardType::none)
{
+ pinMode(DueX_INT, INPUT_PULLUP);
+ pinMode(DueX_SG, INPUT_PULLUP);
+
expander.pinModeMultiple(AllFanBits, OUTPUT_PWM); // Initialise the PWM pins
- expander.pinModeMultiple(AllStopBits, INPUT); // Initialise the endstop inputs (no pullups because 5V-tolerant)
+ const uint16_t stopBits = (boardType == ExpansionBoardType::DueX5) ? AllStopBitsX5 : AllStopBitsX2; // I am assuming that the X0 has 2 endstop inputs
+ expander.pinModeMultiple(stopBits, INPUT); // Initialise the endstop inputs (no pullups because 5V-tolerant)
expander.pinModeMultiple(AllGpioBits, INPUT); // Initialise the GPIO pins as inputs
// Set up the interrupt on any input change
- inputMask = AllStopBits | AllGpioBits;
+ inputMask = stopBits | AllGpioBits;
expander.enableInterruptMultiple(inputMask, CHANGE);
// Clear any initial interrupts
- expander.interruptSource(true);
+ (void)expander.interruptSource(true);
+ inputBits = expander.digitalReadAll();
}
return boardType;
@@ -114,6 +122,10 @@ namespace DuetExpansion
case OUTPUT_PWM:
mode = OUTPUT_PWM_OPEN_DRAIN;
break;
+ case INPUT_PULLUP:
+ case INPUT_PULLDOWN:
+ mode = INPUT; // we are using 5rV-tolerant input with external pullup resistors, so don't enable internal pullup/pulldown resistors
+ break;
default:
break;
}
@@ -127,9 +139,18 @@ namespace DuetExpansion
// We need to use the SX15089 interrupt to read the data register using interrupts, and just retrieve that value here.
bool DigitalRead(Pin pin)
{
- return (boardType != ExpansionBoardType::none)
- ? expander.digitalRead(pin)
- : false;
+ if (boardType == ExpansionBoardType::none || pin >= 16)
+ {
+ return false;
+ }
+
+ if (!digitalRead(DueX_INT))
+ {
+ // Interrupt is active, so input data may have changed
+ inputBits = expander.digitalReadAll();
+ }
+
+ return (inputBits & (1 << pin)) != 0;
}
// Write a pin
diff --git a/src/DuetNG/Pins_DuetNG.h b/src/DuetNG/Pins_DuetNG.h
index f312eb2c..841aeb47 100644
--- a/src/DuetNG/Pins_DuetNG.h
+++ b/src/DuetNG/Pins_DuetNG.h
@@ -54,7 +54,6 @@ const Pin DueX_INT = 17; // DueX interrupt pin = PA17 (was E6_STOP)
// Endstops
// RepRapFirmware only has a single endstop per axis.
// Gcode defines if it is a max ("high end") or min ("low end") endstop and sets if it is active HIGH or LOW.
-//const Pin END_STOP_PINS[DRIVES] = { 46, 02, 93, 74, 48, 96, 97, 98, 99, 17 };
const Pin END_STOP_PINS[DRIVES] = { 46, 02, 93, 74, 48, 200, 203, 202, 201, 213 };
// HEATERS
diff --git a/src/DuetNG/TMC2660.cpp b/src/DuetNG/TMC2660.cpp
index 84c69e9b..fbf96771 100644
--- a/src/DuetNG/TMC2660.cpp
+++ b/src/DuetNG/TMC2660.cpp
@@ -6,6 +6,7 @@
*/
#include "RepRapFirmware.h"
+#include "TMC2660.h"
#if !defined(PROTOTYPE_1)
@@ -25,7 +26,8 @@ const Pin DriversSclkPin = 23; // PA23
#define TMC_CLOCK_CHAN 1
#define TMC_CLOCK_ID ID_TC1 // this is channel 1 on TC0
-const uint32_t DriversSpiClockFrequency = 1000000; // 1MHz SPI clock for now
+const uint32_t DriversSpiClockFrequency = 4000000; // 4MHz SPI clock
+const int StallGuardThreshold = 1; // Range is -64..63. Zero seems to be too sensitive. Higher values reduce sensitivity of stall detection.
// TMC2660 registers
const uint32_t TMC_REG_DRVCTRL = 0;
@@ -100,15 +102,6 @@ const uint32_t TMC_SMARTEN_SEDN_1 = 3 << 13;
const uint32_t TMC_SMARTEN_SEIMIN_HALF = 0 << 15;
const uint32_t TMC_SMARTEN_SEIMIN_QTR = 1 << 15;
-// Read response. The microstep counter can also be read, but we don't include that here.
-const uint32_t TMC_RR_SG = 1 << 0; // stall detected
-const uint32_t TMC_RR_OT = 1 << 1; // over temperature shutdown
-const uint32_t TMC_RR_OTPW = 1 << 2; // over temperature warning
-const uint32_t TMC_RR_S2G = 3 << 3; // short to ground counter (2 bits)
-const uint32_t TMC_RR_OLA = 1 << 5; // open load A
-const uint32_t TMC_RR_OLB = 1 << 6; // open load B
-const uint32_t TMC_RR_STST = 1 << 7; // standstill detected
-
const unsigned int NumWriteRegisters = 5;
// Chopper control register defaults
@@ -125,7 +118,7 @@ const uint32_t defaultChopConfToff = 4; // default value for TOFF when drive is
// StallGuard configuration register
const uint32_t defaultSgscConfReg =
TMC_REG_SGCSCONF
- | 0; // minimum current until user has set it
+ | TMC_SGCSCONF_SGT(StallGuardThreshold);
// Driver configuration register
const uint32_t defaultDrvConfReg =
diff --git a/src/DuetNG/TMC2660.h b/src/DuetNG/TMC2660.h
index 33510340..8fcb267b 100644
--- a/src/DuetNG/TMC2660.h
+++ b/src/DuetNG/TMC2660.h
@@ -10,6 +10,15 @@
#include "Pins.h"
+// TMC2660 Read response. The microstep counter can also be read, but we don't include that here.
+const uint32_t TMC_RR_SG = 1 << 0; // stall detected
+const uint32_t TMC_RR_OT = 1 << 1; // over temperature shutdown
+const uint32_t TMC_RR_OTPW = 1 << 2; // over temperature warning
+const uint32_t TMC_RR_S2G = 3 << 3; // short to ground counter (2 bits)
+const uint32_t TMC_RR_OLA = 1 << 5; // open load A
+const uint32_t TMC_RR_OLB = 1 << 6; // open load B
+const uint32_t TMC_RR_STST = 1 << 7; // standstill detected
+
namespace TMC2660
{
void Init(const Pin[DRIVES], size_t numTmcDrivers)
diff --git a/src/DuetNG/Webserver.cpp b/src/DuetNG/Webserver.cpp
index 0b949c1f..5f67e9f2 100644
--- a/src/DuetNG/Webserver.cpp
+++ b/src/DuetNG/Webserver.cpp
@@ -544,6 +544,7 @@ bool Webserver::ProcessFirstFragment(HttpSession& session, const char* command,
if (timeVal != nullptr && !platform->IsDateTimeSet())
{
struct tm timeInfo;
+ memset(&timeInfo, 0, sizeof(timeInfo));
if (strptime(timeVal, "%Y-%m-%dT%H:%M:%S", &timeInfo) != nullptr)
{
time_t newTime = mktime(&timeInfo);
@@ -623,6 +624,7 @@ bool Webserver::ProcessFirstFragment(HttpSession& session, const char* command,
// Try to obtain the last modified time
time_t fileLastModified = 0;
struct tm timeInfo;
+ memset(&timeInfo, 0, sizeof(timeInfo));
if (timeVal != nullptr && strptime(timeVal, "%Y-%m-%dT%H:%M:%S", &timeInfo) != nullptr)
{
fileLastModified = mktime(&timeInfo);
diff --git a/src/Fan.cpp b/src/Fan.cpp
index b4358238..89e2f972 100644
--- a/src/Fan.cpp
+++ b/src/Fan.cpp
@@ -12,13 +12,13 @@ void Fan::Init(Pin p_pin, bool hwInverted)
val = 0.0;
minVal = 0.1; // 10% minimum fan speed
blipTime = 100; // 100ms fan blip
- blipStartTime = 0;
freq = DefaultFanPwmFreq;
pin = p_pin;
hardwareInverted = hwInverted;
- inverted = false;
+ inverted = blipping = false;
heatersMonitored = 0;
triggerTemperature = HOT_END_FAN_TEMPERATURE;
+ lastPwm = -1.0;
Refresh();
}
@@ -28,10 +28,11 @@ void Fan::SetValue(float speed)
{
speed /= 255.0;
}
- const float newVal = (speed > 0.0) ? constrain<float>(speed, minVal, 1.0) : 0.0;
- if (val == 0.0 && newVal < 1.0 && blipTime != 0)
+ const float newVal = constrain<float>(speed, 0.0, 1.0);
+ if (val == 0.0 && newVal > 0.0 && newVal < 1.0 && blipTime != 0)
{
// Starting the fan from standstill, so blip the fan
+ blipping = true;
blipStartTime = millis();
}
val = newVal;
@@ -68,7 +69,17 @@ void Fan::SetHardwarePwm(float pwmVal)
{
invert = !invert;
}
- Platform::WriteAnalog(pin, (invert) ? (1.0 - pwmVal) : pwmVal, freq);
+ if (invert)
+ {
+ pwmVal = 1.0 - pwmVal;
+ }
+
+ // Only set the PWM if it has changed, to avoid a lot of I2C traffic when we have a DueX5 connected
+ if (pwmVal != lastPwm)
+ {
+ lastPwm = pwmVal;
+ Platform::WriteAnalog(pin, pwmVal, freq);
+ }
}
}
@@ -91,23 +102,31 @@ void Fan::Refresh()
: (reprap.GetPlatform()->AnyHeaterHot(heatersMonitored, triggerTemperature))
? max<float>(0.5, val) // make sure that thermostatic fans always run at 50% speed or more
: 0.0;
- if (reqVal > 0.0 && millis() - blipStartTime < blipTime)
- {
- SetHardwarePwm(1.0);
- }
- else if (reqVal > 0.0 && reqVal < minVal)
+ if (reqVal > 0.0)
{
- SetHardwarePwm(minVal);
- }
- else
- {
- SetHardwarePwm(reqVal);
+ if (reqVal < minVal)
+ {
+ reqVal = minVal;
+ }
+
+ if (blipping)
+ {
+ if (millis() - blipStartTime < blipTime)
+ {
+ reqVal = 1.0;
+ }
+ else
+ {
+ blipping = false;
+ }
+ }
}
+ SetHardwarePwm(reqVal);
}
void Fan::Check()
{
- if (heatersMonitored != 0 || blipTime != 0)
+ if (heatersMonitored != 0 || blipping)
{
Refresh();
}
diff --git a/src/Fan.h b/src/Fan.h
index 9193428b..9e31feb4 100644
--- a/src/Fan.h
+++ b/src/Fan.h
@@ -16,6 +16,7 @@ private:
float val;
float minVal;
float triggerTemperature;
+ float lastPwm;
uint32_t blipTime; // in milliseconds
uint32_t blipStartTime;
uint16_t freq;
@@ -23,6 +24,7 @@ private:
Pin pin;
bool inverted;
bool hardwareInverted;
+ bool blipping;
void Refresh();
void SetHardwarePwm(float pwmVal);
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index 0b0a2a0f..c65b0d01 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -3237,7 +3237,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
const int logicalPin = gb->GetIValue();
Pin pin;
bool invert;
- if (platform->GetFirmwarePin(logicalPin, PinAccess::write, pin, invert))
+ if (platform->GetFirmwarePin(logicalPin, PinAccess::pwm, pin, invert))
{
if (gb->Seen('S'))
{
@@ -4313,7 +4313,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
}
else if (!model.IsEnabled())
{
- reply.printf("Heater %u is disabled");
+ reply.printf("Heater %u is disabled", heater);
}
else
{
@@ -5071,10 +5071,9 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
{
bool seen = false;
bool logicLevel = (gb->Seen('S')) ? (gb->GetIValue() != 0) : true;
- for (size_t axis = 0; axis <= numAxes; ++axis)
+ for (size_t axis = 0; axis < numAxes; ++axis)
{
- const char letter = (axis == numAxes) ? extrudeLetter : axisLetters[axis];
- if (gb->Seen(letter))
+ if (gb->Seen(axisLetters[axis]))
{
int ival = gb->GetIValue();
if (ival >= 0 && ival <= 3)
@@ -5096,8 +5095,6 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
(config == EndStopType::highEndStop) ? "high end" : (config == EndStopType::lowEndStop) ? "low end" : "none",
(config == EndStopType::noEndStop) ? "" : (logic) ? "high" : "low");
}
- platform->GetEndStopConfiguration(E0_AXIS, config, logic);
- reply.catf(" E (active %s)", (logic) ? "high" : "low");
}
}
break;
@@ -5634,7 +5631,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
case 905: // Set current RTC date and time
{
const time_t now = platform->GetDateTime();
- struct tm * const timeInfo = localtime(&now);
+ struct tm * const timeInfo = gmtime(&now);
bool seen = false;
if (gb->Seen('P'))
diff --git a/src/Libraries/Fatfs/fattime_rtc.c b/src/Libraries/Fatfs/fattime_rtc.c
index fc46396f..392e6373 100644
--- a/src/Libraries/Fatfs/fattime_rtc.c
+++ b/src/Libraries/Fatfs/fattime_rtc.c
@@ -60,7 +60,7 @@ uint32_t get_fattime(void);
*
* bit10:5 Minute (0..59)
*
- * bit4:0 Second (0..59)
+ * bit4:0 Second/2 (0..29)
*
* \return Current time.
*/
@@ -84,7 +84,7 @@ uint32_t get_fattime(void)
| (ul_day << 16)
| (ul_hour << 11)
| (ul_minute << 5)
- | (ul_second << 0);
+ | (ul_second >> 1);
return ul_time;
}
diff --git a/src/Platform.cpp b/src/Platform.cpp
index 5a9106ce..bbbf0573 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -339,8 +339,8 @@ void Platform::Init()
// Test for presence of a DueX2 or DueX5 expansion board and work out how many TMC2660 drivers we have
// The SX1509B has an independent power on reset, so give it some time
delay(200);
- ExpansionBoardType et = DuetExpansion::Init();
- switch (et)
+ expansionBoard = DuetExpansion::Init();
+ switch (expansionBoard)
{
case ExpansionBoardType::DueX2:
numTMC2660Drivers = 7;
@@ -578,7 +578,7 @@ int Platform::ZProbe() const
}
}
- return (GetZProbeParameters().invertReading) ? 1023 - zProbeVal : zProbeVal;
+ return (GetZProbeParameters().invertReading) ? 1000 - zProbeVal : zProbeVal;
}
// Return the Z probe secondary values.
@@ -1439,11 +1439,34 @@ void Platform::Diagnostics(MessageType mtype)
AdcReadingToPowerVoltage(lowestVin), AdcReadingToPowerVoltage(currentVin), AdcReadingToPowerVoltage(highestVin),
numUnderVoltageEvents, numOverVoltageEvents);
lowestVin = highestVin = currentVin;
+
+ // Show the motor stall status
+ if (expansionBoard == ExpansionBoardType::DueX2 || expansionBoard == ExpansionBoardType::DueX5)
+ {
+ const bool stalled = digitalRead(DueX_SG);
+ MessageF(mtype, "Expansion motor(s) stall indication: %s\n", (stalled) ? "yes" : "no");
+ }
+
+ for (size_t drive = 0; drive < numTMC2660Drivers; ++drive)
+ {
+ const uint32_t stat = TMC2660::GetStatus(drive);
+ MessageF(mtype, "Driver %d:%s%s%s%s%s%s\n", drive,
+ (stat & TMC_RR_SG) ? " stalled" : "",
+ (stat & TMC_RR_OT) ? " temperature-shutdown!"
+ : (stat & TMC_RR_OTPW) ? " temperature-warning" : "",
+ (stat & TMC_RR_S2G) ? " short-to-ground" : "",
+ ((stat & TMC_RR_OLA) && !(stat & TMC_RR_STST)) ? " open-load-A" : "",
+ ((stat & TMC_RR_OLB) && !(stat & TMC_RR_STST)) ? " open-load-B" : "",
+ (stat & TMC_RR_STST) ? " standstill"
+ : (stat & (TMC_RR_SG | TMC_RR_OT | TMC_RR_OTPW | TMC_RR_S2G | TMC_RR_OLA | TMC_RR_OLB))
+ ? "" : " ok"
+ );
+ }
#endif
// Show current RTC time
const time_t timeNow = RTCDue::GetDateTime();
- const struct tm * const timeInfo = localtime(&timeNow);
+ const struct tm * const timeInfo = gmtime(&timeNow);
MessageF(mtype, "Current date and time: %04u-%02u-%02u %02u:%02u:%02u\n",
timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday,
timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
@@ -2165,9 +2188,14 @@ void Platform::InitFans()
if (NUM_FANS > 1)
{
+#ifdef DUET_NG
// Set fan 1 to be thermostatic by default, monitoring all heaters except the default bed heater
fans[1].SetHeatersMonitored(0xFFFF & ~(1 << BED_HEATER));
fans[1].SetValue(1.0); // set it full on
+#else
+ // Fan 1 on the Duet 0.8.5 shares its control pin with heater 6. Set it full on to make sure the heater (if present) is off.
+ fans[1].SetValue(1.0); // set it full on
+#endif
}
coolingFanRpmPin = COOLING_FAN_RPM_PIN;
@@ -2655,9 +2683,8 @@ bool Platform::GetFirmwarePin(int logicalPin, PinAccess access, Pin& firmwarePin
firmwarePin = SpecialPinMap[logicalPin - 60];
}
#ifdef DUET_NG
- else if (logicalPin >= 100 && logicalPin <= 103) // Pins 100-103 are the GPIO pins on the DueX2/X5
+ else if (logicalPin >= 100 && logicalPin < 100 + (int)ARRAY_SIZE(DueX5GpioPinMap)) // Pins 100-103 are the GPIO pins on the DueX2/X5
{
- static const Pin DueX5GpioPinMap[] = { 211, 210, 209, 208 };
if (access != PinAccess::servo)
{
firmwarePin = DueX5GpioPinMap[logicalPin - 100];
@@ -2669,9 +2696,13 @@ bool Platform::GetFirmwarePin(int logicalPin, PinAccess access, Pin& firmwarePin
{
// Check that the pin mode has been defined suitably
PinMode desiredMode;
- if (access == PinAccess::write || access == PinAccess::servo)
+ if (access == PinAccess::write)
+ {
+ desiredMode = (invert) ? OUTPUT_HIGH : OUTPUT_LOW;
+ }
+ else if (access == PinAccess::pwm || access == PinAccess::servo)
{
- desiredMode = (firmwarePin >= 100) ? OUTPUT_PWM : OUTPUT_LOW;
+ desiredMode = OUTPUT_PWM;
}
else
{
diff --git a/src/Platform.h b/src/Platform.h
index bb274044..e80704d2 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -244,6 +244,7 @@ enum class PinAccess : int
{
read,
write,
+ pwm,
servo
};
@@ -734,6 +735,9 @@ private:
bool autoSaveEnabled;
BoardType board;
+#ifdef DUET_NG
+ ExpansionBoardType expansionBoard;
+#endif
float lastTime;
float longWait;
@@ -802,8 +806,8 @@ private:
float axisMaxima[MAX_AXES];
float axisMinima[MAX_AXES];
- EndStopType endStopType[MAX_AXES+1];
- bool endStopLogicLevel[MAX_AXES+1];
+ EndStopType endStopType[MAX_AXES];
+ bool endStopLogicLevel[MAX_AXES];
// Heaters - bed is assumed to be the first
@@ -1215,14 +1219,14 @@ inline float Platform::GetPressureAdvance(size_t extruder) const
}
inline void Platform::SetEndStopConfiguration(size_t axis, EndStopType esType, bool logicLevel)
-pre(axis < AXES)
+pre(axis < MAX_AXES)
{
endStopType[axis] = esType;
endStopLogicLevel[axis] = logicLevel;
}
inline void Platform::GetEndStopConfiguration(size_t axis, EndStopType& esType, bool& logicLevel) const
-pre(axis < AXES)
+pre(axis < MAX_AXES)
{
esType = endStopType[axis];
logicLevel = endStopLogicLevel[axis];
@@ -1241,19 +1245,21 @@ inline uint16_t Platform::GetRawZProbeReading() const
{
case 4:
{
- bool b = ReadPin(endStopPins[E0_AXIS]);
- if (!endStopLogicLevel[MAX_AXES])
- {
- b = !b;
- }
+ const bool b = ReadPin(endStopPins[E0_AXIS]);
return (b) ? 4000 : 0;
}
case 5:
return (ReadPin(zProbePin)) ? 4000 : 0;
+ case 6:
+ {
+ const bool b = ReadPin(endStopPins[E0_AXIS + 1]);
+ return (b) ? 4000 : 0;
+ }
+
default:
- return AnalogInReadChannel(zProbeAdcChannel);
+ return min<uint16_t>(AnalogInReadChannel(zProbeAdcChannel), 4000);
}
}
diff --git a/src/PrintMonitor.cpp b/src/PrintMonitor.cpp
index c6b92d9a..67dd85a7 100644
--- a/src/PrintMonitor.cpp
+++ b/src/PrintMonitor.cpp
@@ -297,6 +297,7 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GCod
// Set up the info struct
parsedFileInfo.isValid = true;
parsedFileInfo.fileSize = fileBeingParsed->Length();
+ parsedFileInfo.lastModifiedTime = reprap.GetPlatform()->GetMassStorage()->GetLastModifiedTime(directory, fileName);
parsedFileInfo.firstLayerHeight = 0.0;
parsedFileInfo.objectHeight = 0.0;
parsedFileInfo.layerHeight = 0.0;
@@ -613,8 +614,17 @@ bool PrintMonitor::GetFileInfoResponse(const char *filename, OutputBuffer *&resp
return false;
}
- response->printf("{\"err\":0,\"size\":%lu,\"height\":%.2f,\"firstLayerHeight\":%.2f,\"layerHeight\":%.2f,\"filament\":",
- info.fileSize, info.objectHeight, info.firstLayerHeight, info.layerHeight);
+ response->printf("{\"err\":0,\"size\":%lu,",info.fileSize);
+ const struct tm * const timeInfo = gmtime(&info.lastModifiedTime);
+ if (timeInfo->tm_year > /*19*/80)
+ {
+ response->catf("\"lastModified\":\"%04u-%02u-%02uT%02u:%02u:%02u\",",
+ timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday,
+ timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
+ }
+
+ response->catf("\"height\":%.2f,\"firstLayerHeight\":%.2f,\"layerHeight\":%.2f,\"filament\":",
+ info.objectHeight, info.firstLayerHeight, info.layerHeight);
char ch = '[';
if (info.numFilaments == 0)
{
diff --git a/src/PrintMonitor.h b/src/PrintMonitor.h
index 875d43eb..c71770f0 100644
--- a/src/PrintMonitor.h
+++ b/src/PrintMonitor.h
@@ -53,6 +53,7 @@ struct GCodeFileInfo
{
bool isValid;
FilePosition fileSize;
+ time_t lastModifiedTime;
float firstLayerHeight;
float objectHeight;
float filamentNeeded[DRIVES - MIN_AXES];
diff --git a/src/Reprap.cpp b/src/Reprap.cpp
index 5fd174bc..a0a9300e 100644
--- a/src/Reprap.cpp
+++ b/src/Reprap.cpp
@@ -1353,7 +1353,7 @@ OutputBuffer *RepRap::GetFilelistResponse(const char *dir)
if (fileInfo.fileName[0] != '.') // ignore Mac resource files and Linux hidden files
{
// Make sure we can end this response properly
- if (bytesLeft < strlen(fileInfo.fileName) + 80)
+ if (bytesLeft < strlen(fileInfo.fileName) + 70)
{
// No more space available - stop here
break;
@@ -1371,10 +1371,18 @@ OutputBuffer *RepRap::GetFilelistResponse(const char *dir)
bytesLeft -= response->EncodeString(fileInfo.fileName, FILENAME_LENGTH, false);
bytesLeft -= response->catf(",\"size\":%u", fileInfo.size);
- struct tm *timeInfo = localtime(&fileInfo.lastModified);
- bytesLeft -= response->catf(",\"lastModified\":\"%04u-%02u-%02uT%02u:%02u:%02u\"}",
- timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday,
- timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
+ const struct tm * const timeInfo = gmtime(&fileInfo.lastModified);
+ if (timeInfo->tm_year <= /*19*/80)
+ {
+ // Don't send the last modified date if it is invalid
+ bytesLeft -= response->cat('}');
+ }
+ else
+ {
+ bytesLeft -= response->catf(",\"date\":\"%04u-%02u-%02uT%02u:%02u:%02u\"}",
+ timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday,
+ timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec);
+ }
}
gotFile = platform->GetMassStorage()->FindNext(fileInfo);
}
diff --git a/src/Storage/MassStorage.cpp b/src/Storage/MassStorage.cpp
index 5df45663..945045c9 100644
--- a/src/Storage/MassStorage.cpp
+++ b/src/Storage/MassStorage.cpp
@@ -159,16 +159,7 @@ bool MassStorage::FindFirst(const char *directory, FileInfo &file_info)
}
file_info.size = entry.fsize;
-
- struct tm timeInfo;
- timeInfo.tm_year = (entry.fdate >> 9) + 80;
- timeInfo.tm_mon = (entry.fdate & 0x1DF) >> 5;
- timeInfo.tm_mday = max<int>(entry.fdate & 0x1F, 1);
- timeInfo.tm_hour = (entry.ftime >> 11) & 0x1F;
- timeInfo.tm_min = (entry.ftime >> 5) & 0x3F;
- timeInfo.tm_sec = entry.ftime & 0x1F;
- timeInfo.tm_isdst = -1;
- file_info.lastModified = mktime(&timeInfo);
+ file_info.lastModified = ConvertTimeStamp(entry.fdate, entry.ftime);
return true;
}
@@ -199,16 +190,7 @@ bool MassStorage::FindNext(FileInfo &file_info)
strncpy(file_info.fileName, entry.fname, ARRAY_SIZE(file_info.fileName));
}
- struct tm timeInfo;
- timeInfo.tm_year = (entry.fdate >> 9) + 80;
- timeInfo.tm_mon = (entry.fdate & 0x1DF) >> 5;
- timeInfo.tm_mday = max<int>(entry.fdate & 0x1F, 1);
- timeInfo.tm_hour = (entry.ftime >> 11) & 0x1F;
- timeInfo.tm_min = (entry.ftime >> 5) & 0x3F;
- timeInfo.tm_sec = entry.ftime & 0x1F;
- timeInfo.tm_isdst = -1;
- file_info.lastModified = mktime(&timeInfo);
-
+ file_info.lastModified = ConvertTimeStamp(entry.fdate, entry.ftime);
return true;
}
@@ -297,14 +279,28 @@ bool MassStorage::DirectoryExists(const char* directory, const char* subDirector
return DirectoryExists(CombineName(directory, subDirectory));
}
+// Return the last modified time of a file, or zero if failure
+time_t MassStorage::GetLastModifiedTime(const char* directory, const char *fileName) const
+{
+ const char *location = (directory != nullptr)
+ ? platform->GetMassStorage()->CombineName(directory, fileName)
+ : fileName;
+ FILINFO fil;
+ fil.lfname = nullptr;
+ if (f_stat(location, &fil) == FR_OK)
+ {
+ return ConvertTimeStamp(fil.fdate, fil.ftime);
+ }
+ return 0;
+}
+
bool MassStorage::SetLastModifiedTime(const char *file, time_t time)
{
FILINFO fno;
- const struct tm * const timeInfo = localtime(&time);
+ const struct tm * const timeInfo = gmtime(&time);
fno.fdate = (WORD)(((timeInfo->tm_year - 80) * 512U) | (timeInfo->tm_mon + 1) * 32U | timeInfo->tm_mday);
fno.ftime = (WORD)(timeInfo->tm_hour * 2048U | timeInfo->tm_min * 32U | timeInfo->tm_sec / 2U);
-
const bool ok = (f_utime(file, &fno) == FR_OK);
if (!ok)
{
@@ -426,4 +422,19 @@ bool MassStorage::CheckDriveMounted(const char* path)
return card < NumSdCards && isMounted[card];
}
+/*static*/ time_t MassStorage::ConvertTimeStamp(uint16_t fdate, uint16_t ftime)
+{
+ struct tm timeInfo;
+ memset(&timeInfo, 0, sizeof(timeInfo));
+ timeInfo.tm_year = (fdate >> 9) + 80;
+ const uint16_t month = (fdate >> 5) & 0x0F;
+ timeInfo.tm_mon = (month == 0) ? month : month - 1; // month is 1..12 in FAT but 0..11 in struct tm
+ timeInfo.tm_mday = max<int>(fdate & 0x1F, 1);
+ timeInfo.tm_hour = (ftime >> 11) & 0x1F;
+ timeInfo.tm_min = (ftime >> 5) & 0x3F;
+ timeInfo.tm_sec = ftime & 0x1F;
+ timeInfo.tm_isdst = 0;
+ return mktime(&timeInfo);
+}
+
// End
diff --git a/src/Storage/MassStorage.h b/src/Storage/MassStorage.h
index 0d17b439..3ccf973d 100644
--- a/src/Storage/MassStorage.h
+++ b/src/Storage/MassStorage.h
@@ -30,6 +30,7 @@ public:
bool FileExists(const char* directory, const char *fileName) const;
bool DirectoryExists(const char *path) const;
bool DirectoryExists(const char* directory, const char* subDirectory);
+ time_t GetLastModifiedTime(const char* directory, const char *fileName) const;
bool SetLastModifiedTime(const char *file, time_t time);
bool Mount(size_t card, StringRef& reply, bool reportSuccess);
bool Unmount(size_t card, StringRef& reply);
@@ -44,6 +45,8 @@ protected:
void Init();
private:
+ static time_t ConvertTimeStamp(uint16_t fdate, uint16_t ftime);
+
Platform* platform;
FATFS fileSystems[NumSdCards];
DIR findDir;