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
diff options
context:
space:
mode:
authorDavid Crocker <dcrocker@eschertech.com>2018-06-05 20:20:10 +0300
committerDavid Crocker <dcrocker@eschertech.com>2018-06-05 20:20:10 +0300
commit5db504363ecf7a00c2f1a687cadb29bda47c7f1e (patch)
tree7f5bd04a5ea46fb8f5d98c4cfb75494d146000a4
parent75c87d6e85cfe8678f24fe09520d43923634179b (diff)
Version 2.0 provisional2.0
New features/changed behaviour: - if config.g is not found then config.g.bak is run instead of default.g - added error codes to SD card access error reports - rr_files, rr_filelist, M20 S2 and M20 S3 now provide for retrieving the list if files in chunks, using a "first" parameter in rr_files/rr_filelist or "R" parameter in M20 S2/S2, and a "next" field in the response Bug fixes: - In absolute extrusion mode, the first move when resuming after a pause didn't extrude - DWC didn't give the option to load a filament when no filament was loaded
-rw-r--r--src/BugList.txt61
-rw-r--r--src/Configuration.h2
-rw-r--r--src/Duet/Webserver.cpp10
-rw-r--r--src/GCodes/GCodes.cpp3
-rw-r--r--src/GCodes/GCodes2.cpp7
-rw-r--r--src/Heating/Sensors/DhtSensor.cpp23
-rw-r--r--src/Libraries/Fatfs/ff.h6
-rw-r--r--src/Networking/HttpResponder.cpp10
-rw-r--r--src/OutputMemory.cpp6
-rw-r--r--src/OutputMemory.h2
-rw-r--r--src/Platform.h2
-rw-r--r--src/RepRap.cpp236
-rw-r--r--src/RepRap.h4
-rw-r--r--src/Storage/FileStore.cpp10
-rw-r--r--src/Version.h4
15 files changed, 206 insertions, 180 deletions
diff --git a/src/BugList.txt b/src/BugList.txt
index 41a4892b..619a7bcd 100644
--- a/src/BugList.txt
+++ b/src/BugList.txt
@@ -162,7 +162,7 @@ Fixes in RC5:
- [done] Extra axes were ignored in G2/G3 moves
- [done] DWC and the Duet could deadlock if the Duet ran out of output buffers
-Fixes post RC5:
+Fixes in RC6:
- [done] M569 report includes chopper configuration register for smart drivers
- [done] If getting file info timed out it didn't close the file
- [done] DHT sensor task was running out of stack space
@@ -171,50 +171,69 @@ Fixes post RC5:
- [done] Multiple DHT sensor support
- [done] Support DHT sensor on Duet Maestro
- [done] Pausing between the segments of a segmented move didn't happen even if the jerk settings were high enough
-- [done - need to test filament monitors!!!] If filament monitors were deleted or the type changed, this could result in an exception
-- [seems ok] Test Upload & print function, see https://forum.duet3d.com/topic/5394/new-firmware-2-0rc5-available/52
+- [done, ok] If filament monitors were deleted or the type changed, this could result in an exception
+- [done] Support S0/S1 for simple filament monitors
- [done, test] When step rate limiting happens, various problems, see https://forum.duet3d.com/topic/5445/unable-to-run-128-or-256-microstepping (adjust move start time)
-- [can't reproduce] Kulitorum report that first move after a pause doesn't extrude, https://forum.duet3d.com/topic/5408/does-not-extrude-first-g1-after-a-pause/7
- [done, test] when the SD card is removed it says 1 file was invalidated even if it was more
- [done, ok] When SD card is removed during a print we get lots of internal error messages, and no "print abandoned" or similar message, also the heaters stay on
- [done] Emergency stop should turn off all spindles
-- [looks like was caused by using M502] Report that filaments no longer work
+- [seems ok] Test Upload & print function, see https://forum.duet3d.com/topic/5394/new-firmware-2-0rc5-available/52
+
+Fixes in release 2.0:
+- [done, test] Kulitorum report that first move after a pause doesn't extrude, https://forum.duet3d.com/topic/5408/does-not-extrude-first-g1-after-a-pause/7
+- [done] Add error codes to SD card error messages
+- [tested, documentation error] chrishamm says DHT sensors on CS pins 1-4 don't work
+- [done] add facility to return rr_filelist in chunks?
+- [done] load config.g.bak if config.g not present, not default.g
+- [done] can't load filaments because DWC doesn't give the option unless a filament is already loaded
+- look at wifi disconnect issue, https://forum.duet3d.com/topic/4341/wifi-module-keeps-disconnecting/64
+
+Planned for 2.01:
+- Bezier speed curves or other S-curve acceleration, e.g. look at https://github.com/MarlinFirmware/Marlin/pull/10373/files
+- Option to send M280 servo commands just a few times instead of continuously, for E3D and BLTouch
+- Recovery from SD card errors during a print (Dan)
+- Danny's modified SCARA kinematics (workpiece is on a plate, extruder is fixed)
+- Laser support via G1 S parameter, see https://forum.duet3d.com/topic/4702/laser-cnc-support-in-rrf-gcode-semantics/4
+- Look at pushover notification support, https://forum.duet3d.com/topic/169/notification-via-pushover-or-other-service/45
- M3 R parameter so it can restore the spinder/laser after a pause (https://forum.duet3d.com/topic/5418/cnc-laser-m3-unpause-r-parameter)
+- M81: don't give low voltage warnings when main power has just been turned off
+- Does bltouch need a default recovery time?
+- Should bltouch use digital probe mode? Some users having problems with P25 in G31 command.
+- M584 when assigning a drive, unmap any existing assignment. Also allow an axis to be mapped to driver -1.
+- Add S4 option to G1 command, like S1 but no endstop checks (needed for CoreXY, CoreXZ)
- CNC: look at G17/18/19, see https://forum.duet3d.com/topic/4669/ooznest-workbee-screw-driven
-- PanelDue won't connect if VIN velow minimum for stepper motors [PanelDue firmware needs to recognise status 'O']
+- M569 command to allow selection of smart/dumb driver, also allow all 12 drivers to be smart
+- M569 TOFF parameter, https://forum.duet3d.com/topic/5392/does-m906-set-rms-or-peak-current/28
+- Apostrophe in quoted filename: can we make apostrophe special in SSIDs/passwords but not filenames?
+- If wifi module gets stuck in starting or changing mode state, reset it again
+- If wifi disconnects when in client mode, keep retrying the connection
+
+Other (some of these may be in 2.01):
+- Update PanelDue firmware via Duet
+- Use Heat task to read DHT sensors?
+- Add option R4 to M915 command, to do an emergency stop (useful for Z motor)
+- GCodes corresponding to rr_move and rr_mkdir, https://forum.duet3d.com/topic/5470/firmware-2-0rc6-and-1-21-1rc6-released/13
- Add parameter to M116 to specify acceptable temperature difference
-- Laser support, see https://forum.duet3d.com/topic/4702/laser-cnc-support-in-rrf-gcode-semantics/4
-- Pushover notification support, https://forum.duet3d.com/topic/169/notification-via-pushover-or-other-service/45
- support M205 for setting jerk
- support G12 clean tool?
- Add fan PWM limit, https://forum.duet3d.com/topic/5370/m106-feature-request-limit-max-pwm-parameter/4
- M116 extra "close enough" parameter
-- Danny's modified SCARA kinematics (workpiece is on a plate, extruder is fixed)
-- Look at Bezier speed curves or other S-curve acceleration, https://github.com/MarlinFirmware/Marlin/pull/10373/files
- after homing, warn if outside M208 movement limits on SCARA, polar etc.
- Unexpected heaters off/tool selection behaviour, https://www.duet3d.com/forum/thread.php?pid=43059#p43059
- warn when using : where ; was probably meant
- Error message if you attempt movement with VIN < minimum
- min/max RSSI display?
-- save theta, phi in move and then in DDA?
- report RSSI in M552?
- When VIN power too low and stepper drivers turned off, flag axes as not homed?
-- M81: don't give low voltage warnings when main power has just been turned off
-- Return "Powered down" status when VIN power has never been seen or has gone down after sending M81
- Auto mount main SD card when inserted
- Workplace offsets are supposed to be persistant (check NIST), https://www.duet3d.com/forum/thread.php?pid=43755#p43755
- At the end of a simulation, restore the original workplace coordinate selection
-- apostrophe in quoted filename
- looks like we get a Pop underflow message when you send DWC jog commands and axes are not homed
- Add warning message when print exceeds bounds
-- Does bltouch need a default recovery time?
-- Should bltouch use digital probe mode? Some users having problems with P25 in G31 command.
-- M584 when assigning a drive, unmap any existing assignment. Also allow an axis to be mapped to driver -1.
-- Add S4 option to G1 command, like S1 but no endstop checks (needed for CoreXY, CoreXZ)
- When uploading while a file is being printed, don't allow the currently-printing file to be replaced
-- if a homing command in an SD print file is aborted due to e.g. G1 Z5 in the homing file, error message should be written to both DWC and PanelDue
+- [check] if a homing command in an SD print file is aborted due to e.g. G1 Z5 in the homing file, error message should be written to both DWC and PanelDue
- [no fault] stall detect on Z axis
- Files generated by Cura doesn't detect layer changes, see https://www.duet3d.com/forum/thread.php?pid=40865#p40865
- [re-test using new DuetWiFiServer] "Failed to change mode" messages after M552 S2/S0/S1 cycle
@@ -231,7 +250,6 @@ Fixes post RC5:
- check that we never enable the drivers before we set vsense
- [don't do] Don't report the motor current for a non-existent extruder
-- SD card read error handling?
- dual extrusion layer counting, see https://www.duet3d.com/forum/thread.php?pid=34816#p34816
- M140/M190 with no P parameter sets all bed heater temperatures (same for M141/M191)
- M291 to lock movement and wait for it to finish?
@@ -245,9 +263,6 @@ Fixes post RC5:
- Send reduce power command to PanelDue when main power turned off?
- Document multiple bed and chamber heaters
- [mostly done] Check all classes for correct initialisation
-- sd_mmc_spi doesn't acquire/release the SPI bus. Need to change this for RTOS.
-- If wifi module gets stuck in starting state, reset it again
-- If wifi disconnects when in client mode, keep retrying the connection
Bug investigations:
- [done] step errors, https://www.duet3d.com/forum/thread.php?pid=33741#p33741
diff --git a/src/Configuration.h b/src/Configuration.h
index 3a94dfd6..13f5c9d8 100644
--- a/src/Configuration.h
+++ b/src/Configuration.h
@@ -259,7 +259,7 @@ constexpr size_t FILE_BUFFER_SIZE = 128;
#define MENU_DIR "0:/menu/" // Directory for menu files
#define CONFIG_FILE "config.g"
-#define DEFAULT_FILE "default.g"
+#define CONFIG_BACKUP_FILE "config.g.bak"
#define DEFAULT_LOG_FILE "eventlog.txt"
#define EOF_STRING "<!-- **EoF** -->"
diff --git a/src/Duet/Webserver.cpp b/src/Duet/Webserver.cpp
index cb163698..3ec41216 100644
--- a/src/Duet/Webserver.cpp
+++ b/src/Duet/Webserver.cpp
@@ -951,19 +951,23 @@ void Webserver::HttpInterpreter::GetJsonResponse(const char* request, OutputBuff
else if (StringEquals(request, "filelist") && GetKeyValue("dir") != nullptr)
{
OutputBuffer::Release(response);
- response = reprap.GetFilelistResponse(GetKeyValue("dir"));
+ const char* const firstVal = GetKeyValue("first");
+ const unsigned int startAt = (firstVal == nullptr) ? 0 : (unsigned int)SafeStrtol(firstVal);
+ response = reprap.GetFilelistResponse(GetKeyValue("dir"), startAt); // this may return nullptr
}
else if (StringEquals(request, "files"))
{
+ OutputBuffer::Release(response);
const char* dir = GetKeyValue("dir");
if (dir == nullptr)
{
dir = platform->GetGCodeDir();
}
+ const char* const firstVal = GetKeyValue("first");
+ const unsigned int startAt = (firstVal == nullptr) ? 0 : SafeStrtol(firstVal);
const char* const flagDirsVal = GetKeyValue("flagDirs");
const bool flagDirs = flagDirsVal != nullptr && atoi(flagDirsVal) == 1;
- OutputBuffer::Release(response);
- response = reprap.GetFilesResponse(dir, flagDirs);
+ response = reprap.GetFilesResponse(dir, startAt, flagDirs); // this may return nullptr
}
else if (StringEquals(request, "fileinfo"))
{
diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp
index 44bc3075..47f7947e 100644
--- a/src/GCodes/GCodes.cpp
+++ b/src/GCodes/GCodes.cpp
@@ -2115,11 +2115,11 @@ bool GCodes::LoadExtrusionAndFeedrateFromGCode(GCodeBuffer& gb)
moveBuffer.coords[drive] = 0.0;
}
moveBuffer.hasExtrusion = false;
+ moveBuffer.virtualExtruderPosition = virtualExtruderPosition; // save this before we update it
// Check if we are extruding
if (moveBuffer.isCoordinated && gb.Seen(extrudeLetter))
{
-
// Check that we have a tool to extrude with
Tool* const tool = reprap.GetCurrentTool();
if (tool == nullptr)
@@ -2610,7 +2610,6 @@ void GCodes::FinaliseMove(GCodeBuffer& gb)
{
moveBuffer.canPauseAfter = (moveBuffer.endStopsToCheck == 0);
moveBuffer.filePos = (&gb == fileGCode) ? gb.GetFilePosition(fileInput->BytesCached()) : noFilePosition;
- moveBuffer.virtualExtruderPosition = virtualExtruderPosition;
if (totalSegments > 1)
{
diff --git a/src/GCodes/GCodes2.cpp b/src/GCodes/GCodes2.cpp
index 7d8d78e4..af298d35 100644
--- a/src/GCodes/GCodes2.cpp
+++ b/src/GCodes/GCodes2.cpp
@@ -564,6 +564,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
}
{
const int sparam = (gb.Seen('S')) ? gb.GetIValue() : 0;
+ const unsigned int rparam = (gb.Seen('R')) ? gb.GetUIValue() : 0;
String<MaxFilenameLength> dir;
if (gb.Seen('P'))
{
@@ -577,7 +578,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
OutputBuffer *fileResponse;
if (sparam == 2)
{
- fileResponse = reprap.GetFilesResponse(dir.c_str(), true); // Send the file list in JSON format
+ fileResponse = reprap.GetFilesResponse(dir.c_str(), rparam, true); // send the file list in JSON format
if (fileResponse == nullptr)
{
return false;
@@ -586,7 +587,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
}
else if (sparam == 3)
{
- fileResponse = reprap.GetFilelistResponse(dir.c_str());
+ fileResponse = reprap.GetFilelistResponse(dir.c_str(), rparam);
if (fileResponse == nullptr)
{
return false;
@@ -597,7 +598,7 @@ bool GCodes::HandleMcode(GCodeBuffer& gb, const StringRef& reply)
{
if (!OutputBuffer::Allocate(fileResponse))
{
- return false; // Cannot allocate an output buffer, try again later
+ return false; // cannot allocate an output buffer, try again later
}
// To mimic the behaviour of the official RepRapPro firmware:
diff --git a/src/Heating/Sensors/DhtSensor.cpp b/src/Heating/Sensors/DhtSensor.cpp
index 016723af..15da14bb 100644
--- a/src/Heating/Sensors/DhtSensor.cpp
+++ b/src/Heating/Sensors/DhtSensor.cpp
@@ -39,6 +39,7 @@ DhtSensorHardwareInterface::DhtSensorHardwareInterface(Pin p_pin)
: sensorPin(p_pin), type(DhtSensorType::none), lastResult(TemperatureError::notInitialised),
lastTemperature(BAD_ERROR_TEMPERATURE), lastHumidity(BAD_ERROR_TEMPERATURE), badTemperatureCount(0)
{
+ IoPort::SetPinMode(sensorPin, INPUT_PULLUP);
}
TemperatureError DhtSensorHardwareInterface::GetTemperatureOrHumidity(float& t, bool wantHumidity) const
@@ -117,7 +118,7 @@ GCodeResult DhtSensorHardwareInterface::Configure(TemperatureSensor *ts, unsigne
return rslt;
}
-// Create a hardware interface object re the specified channel if there isn't already
+// Create a hardware interface object for the specified channel if there isn't already
DhtSensorHardwareInterface *DhtSensorHardwareInterface::Create(unsigned int relativeChannel)
{
if (relativeChannel >= MaxSpiTempSensors)
@@ -170,19 +171,13 @@ void DhtSensorHardwareInterface::Interrupt()
if (numPulses < ARRAY_SIZE(pulses))
{
const uint16_t now = Platform::GetInterruptClocks16();
- if (digitalRead(sensorPin))
+ if (IoPort::ReadPin(sensorPin))
{
lastPulseTime = now;
}
else if (lastPulseTime != 0)
{
pulses[numPulses++] = now - lastPulseTime;
-#if 0
- if (numPulses == ARRAY_SIZE(pulses))
- {
- vTaskNotifyGiveFromISR(dhtTask->GetHandle(), nullptr); // wake up the task
- }
-#endif
}
}
}
@@ -191,12 +186,8 @@ void DhtSensorHardwareInterface::TakeReading()
{
if (type != DhtSensorType::none) // if sensor has been configured
{
- // Send start signal. See DHT datasheet for full signal diagram:
- // http://www.adafruit.com/datasheets/Digital%20humidity%20and%20temperature%20sensor%20AM2302.pdf
- pinMode(sensorPin, OUTPUT_HIGH);
- delay(250);
-
- digitalWrite(sensorPin, LOW);
+ // Send the start bit. This must be at least 18ms for the DHT11, 0.8ms for the DHT21, and 1ms long for the DHT22.
+ IoPort::SetPinMode(sensorPin, OUTPUT_LOW);
delay(20);
{
@@ -204,11 +195,11 @@ void DhtSensorHardwareInterface::TakeReading()
// End the start signal by setting data line high. the sensor will respond with the start bit in 20 to 40us.
// We need only force the data line high long enough to charge the line capacitance, after that the pullup resistor keeps it high.
- digitalWrite(sensorPin, HIGH); // this will generate an interrupt, but we will ignore it
+ IoPort::WriteDigital(sensorPin, HIGH); // this will generate an interrupt, but we will ignore it
delayMicroseconds(3);
// Now start reading the data line to get the value from the DHT sensor
- pinMode(sensorPin, INPUT_PULLUP);
+ IoPort::SetPinMode(sensorPin, INPUT_PULLUP);
// It appears that switching the pin to an output disables the interrupt, so we need to call attachInterrupt here
// We are likely to get an immediate interrupt at this point corresponding to the low-to-high transition. We must ignore this.
diff --git a/src/Libraries/Fatfs/ff.h b/src/Libraries/Fatfs/ff.h
index 406f9d29..7f0d91ab 100644
--- a/src/Libraries/Fatfs/ff.h
+++ b/src/Libraries/Fatfs/ff.h
@@ -178,14 +178,14 @@ typedef struct {
typedef enum {
FR_OK = 0, /* (0) Succeeded */
- FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */
+ FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
- FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */
- FR_EXIST, /* (8) Acces denied due to prohibited access */
+ FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
+ FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
diff --git a/src/Networking/HttpResponder.cpp b/src/Networking/HttpResponder.cpp
index 00ee1145..b96fcac2 100644
--- a/src/Networking/HttpResponder.cpp
+++ b/src/Networking/HttpResponder.cpp
@@ -533,19 +533,23 @@ bool HttpResponder::GetJsonResponse(const char* request, OutputBuffer *&response
else if (StringEquals(request, "filelist") && GetKeyValue("dir") != nullptr)
{
OutputBuffer::Release(response);
- response = reprap.GetFilelistResponse(GetKeyValue("dir")); // this may return nullptr
+ const char* const firstVal = GetKeyValue("first");
+ const unsigned int startAt = (firstVal == nullptr) ? 0 : (unsigned int)SafeStrtol(firstVal);
+ response = reprap.GetFilelistResponse(GetKeyValue("dir"), startAt); // this may return nullptr
}
else if (StringEquals(request, "files"))
{
+ OutputBuffer::Release(response);
const char* dir = GetKeyValue("dir");
if (dir == nullptr)
{
dir = GetPlatform().GetGCodeDir();
}
+ const char* const firstVal = GetKeyValue("first");
+ const unsigned int startAt = (firstVal == nullptr) ? 0 : SafeStrtol(firstVal);
const char* const flagDirsVal = GetKeyValue("flagDirs");
const bool flagDirs = flagDirsVal != nullptr && SafeStrtol(flagDirsVal) == 1;
- OutputBuffer::Release(response);
- response = reprap.GetFilesResponse(dir, flagDirs); // this may return nullptr
+ response = reprap.GetFilesResponse(dir, startAt, flagDirs); // this may return nullptr
}
else if (StringEquals(request, "fileinfo"))
{
diff --git a/src/OutputMemory.cpp b/src/OutputMemory.cpp
index d7f49728..22200a1f 100644
--- a/src/OutputMemory.cpp
+++ b/src/OutputMemory.cpp
@@ -231,13 +231,17 @@ size_t OutputBuffer::cat(StringRef &str)
}
// Encode a string in JSON format and append it to a string buffer and return the number of bytes written
-size_t OutputBuffer::EncodeString(const char *src, size_t srcLength, bool allowControlChars, bool encapsulateString)
+size_t OutputBuffer::EncodeString(const char *src, size_t srcLength, bool allowControlChars, bool encapsulateString, bool prependAsterisk)
{
size_t bytesWritten = 0;
if (encapsulateString)
{
bytesWritten += cat('"');
}
+ if (prependAsterisk)
+ {
+ bytesWritten += cat('*');
+ }
if (srcLength != 0)
{
diff --git a/src/OutputMemory.h b/src/OutputMemory.h
index 4fcdc442..c5d31787 100644
--- a/src/OutputMemory.h
+++ b/src/OutputMemory.h
@@ -54,7 +54,7 @@ class OutputBuffer
size_t cat(const char *src, size_t len);
size_t cat(StringRef &str);
- size_t EncodeString(const char *src, size_t srcLength, bool allowControlChars, bool encapsulateString = true);
+ size_t EncodeString(const char *src, size_t srcLength, bool allowControlChars, bool encapsulateString = true, bool prependAsterisk = false);
size_t EncodeString(const StringRef& str, bool allowControlChars, bool encapsulateString = true);
size_t EncodeReply(OutputBuffer *src, bool allowControlChars);
diff --git a/src/Platform.h b/src/Platform.h
index 5c448de2..9d040849 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -952,7 +952,7 @@ inline const char* Platform::GetConfigFile() const
inline const char* Platform::GetDefaultFile() const
{
- return DEFAULT_FILE;
+ return CONFIG_BACKUP_FILE;
}
//*****************************************************************************************************************
diff --git a/src/RepRap.cpp b/src/RepRap.cpp
index 443aaed2..914b860a 100644
--- a/src/RepRap.cpp
+++ b/src/RepRap.cpp
@@ -1254,11 +1254,15 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source)
if (tool->GetFilament() != nullptr)
{
const char *filamentName = tool->GetFilament()->GetName();
+#if 0 // DC this change broke filament loading/unloading in DWC
if (filamentName[0] != 0)
{
+#endif
response->catf(",\"filament\":");
response->EncodeString(filamentName, strlen(filamentName), false);
+#if 0 // DC see above
}
+#endif
}
// Offsets
@@ -1681,7 +1685,7 @@ OutputBuffer *RepRap::GetLegacyStatusResponse(uint8_t type, int seq)
// Get the list of files in the specified directory in JSON format.
// If flagDirs is true then we prefix each directory with a * character.
-OutputBuffer *RepRap::GetFilesResponse(const char *dir, bool flagsDirs)
+OutputBuffer *RepRap::GetFilesResponse(const char *dir, unsigned int startAt, bool flagsDirs)
{
// Need something to write to...
OutputBuffer *response;
@@ -1692,8 +1696,9 @@ OutputBuffer *RepRap::GetFilesResponse(const char *dir, bool flagsDirs)
response->copy("{\"dir\":");
response->EncodeString(dir, strlen(dir), false);
- response->cat(",\"files\":[");
+ response->catf(",\"first\":%u,\"files\":[", startAt);
unsigned int err;
+ unsigned int nextFile = 0;
if (!platform->GetMassStorage()->CheckDriveMounted(dir))
{
@@ -1707,50 +1712,138 @@ OutputBuffer *RepRap::GetFilesResponse(const char *dir, bool flagsDirs)
{
err = 0;
FileInfo fileInfo;
- bool firstFile = true;
+ unsigned int filesFound = 0;
bool gotFile = platform->GetMassStorage()->FindFirst(dir, fileInfo); // TODO error handling here
size_t bytesLeft = OutputBuffer::GetBytesLeft(response); // don't write more bytes than we can
- char filename[MaxFilenameLength];
- filename[0] = '*';
- const char *fname;
while (gotFile)
{
if (fileInfo.fileName[0] != '.') // ignore Mac resource files and Linux hidden files
{
- // Get the long filename if possible
- if (flagsDirs && fileInfo.isDirectory)
- {
- SafeStrncpy(filename + 1, fileInfo.fileName, ARRAY_SIZE(fileInfo.fileName) - 1);
- fname = filename;
- }
- else
+ if (filesFound >= startAt)
{
- fname = fileInfo.fileName;
- }
+ // Make sure we can end this response properly
+ if (bytesLeft < strlen(fileInfo.fileName) * 2 + 20)
+ {
+ // No more space available - stop here
+ platform->GetMassStorage()->AbandonFindNext();
+ nextFile = filesFound;
+ break;
+ }
- // Make sure we can end this response properly
- if (bytesLeft < strlen(fname) * 2 + 4)
- {
- // No more space available - stop here
- platform->GetMassStorage()->AbandonFindNext();
- break;
+ // Write separator and filename
+ if (filesFound > startAt)
+ {
+ bytesLeft -= response->cat(',');
+ }
+
+ bytesLeft -= response->EncodeString(fileInfo.fileName, MaxFilenameLength, false, true, flagsDirs && fileInfo.isDirectory);
}
+ ++filesFound;
+ }
+ gotFile = platform->GetMassStorage()->FindNext(fileInfo); // TODO error handling here
+ }
+ }
+
+ if (err != 0)
+ {
+ response->catf("],\"err\":%u}", err);
+ }
+ else
+ {
+ response->catf("],\"next\":%u,\"err\":%u}", nextFile, err);
+ }
+ return response;
+}
+
+// Get a JSON-style filelist including file types and sizes
+OutputBuffer *RepRap::GetFilelistResponse(const char *dir, unsigned int startAt)
+{
+ // Need something to write to...
+ OutputBuffer *response;
+ if (!OutputBuffer::Allocate(response))
+ {
+ return nullptr;
+ }
+
+ response->copy("{\"dir\":");
+ response->EncodeString(dir, strlen(dir), false);
+ response->catf(",\"first\":%u,\"files\":[", startAt);
+ unsigned int err;
+ unsigned int nextFile = 0;
+
+ if (!platform->GetMassStorage()->CheckDriveMounted(dir))
+ {
+ err = 1;
+ }
+ else if (!platform->GetMassStorage()->DirectoryExists(dir))
+ {
+ err = 2;
+ }
+ else
+ {
+ err = 0;
+ FileInfo fileInfo;
+ unsigned int filesFound = 0;
+ bool gotFile = platform->GetMassStorage()->FindFirst(dir, fileInfo);
+ size_t bytesLeft = OutputBuffer::GetBytesLeft(response); // don't write more bytes than we can
- // Write separator and filename
- if (!firstFile)
+ while (gotFile)
+ {
+ if (fileInfo.fileName[0] != '.') // ignore Mac resource files and Linux hidden files
+ {
+ if (filesFound >= startAt)
{
- bytesLeft -= response->cat(',');
- }
- bytesLeft -= response->EncodeString(fname, MaxFilenameLength, false);
+ // Make sure we can end this response properly
+ if (bytesLeft < strlen(fileInfo.fileName) * 2 + 50)
+ {
+ // No more space available - stop here
+ platform->GetMassStorage()->AbandonFindNext();
+ nextFile = filesFound;
+ break;
+ }
+
+ // Write delimiter
+ if (filesFound != 0)
+ {
+ bytesLeft -= response->cat(',');
+ }
+
+ // Write another file entry
+ bytesLeft -= response->catf("{\"type\":\"%c\",\"name\":", fileInfo.isDirectory ? 'd' : 'f');
+ bytesLeft -= response->EncodeString(fileInfo.fileName, MaxFilenameLength, false);
+ bytesLeft -= response->catf(",\"size\":%" PRIu32, fileInfo.size);
- firstFile = false;
+ 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);
+ }
+ }
+ ++filesFound;
}
- gotFile = platform->GetMassStorage()->FindNext(fileInfo); // TODO error handling here
+ gotFile = platform->GetMassStorage()->FindNext(fileInfo);
}
}
- response->catf("],\"err\":%u}", err);
+
+ // If there is no error, don't append "err":0 because if we do then DWC thinks there has been an error - looks like it doesn't check the value
+ if (err != 0)
+ {
+ response->catf("],\"err\":%u}", err);
+ }
+ else
+ {
+ response->catf("],\"next\":%u}", nextFile);
+ }
+
return response;
}
@@ -1840,91 +1933,6 @@ bool RepRap::GetFileInfoResponse(const char *filename, OutputBuffer *&response,
return true;
}
-// Get a JSON-style filelist including file types and sizes
-OutputBuffer *RepRap::GetFilelistResponse(const char *dir)
-{
- // Need something to write to...
- OutputBuffer *response;
- if (!OutputBuffer::Allocate(response))
- {
- return nullptr;
- }
-
- response->copy("{\"dir\":");
- response->EncodeString(dir, strlen(dir), false);
- response->cat(",\"files\":[");
- unsigned int err;
-
- if (!platform->GetMassStorage()->CheckDriveMounted(dir))
- {
- err = 1;
- }
- else if (!platform->GetMassStorage()->DirectoryExists(dir))
- {
- err = 2;
- }
- else
- {
- err = 0;
- FileInfo fileInfo;
- bool firstFile = true;
- bool gotFile = platform->GetMassStorage()->FindFirst(dir, fileInfo);
- size_t bytesLeft = OutputBuffer::GetBytesLeft(response); // don't write more bytes than we can
-
- while (gotFile)
- {
- 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) + 70)
- {
- // No more space available - stop here
- platform->GetMassStorage()->AbandonFindNext();
- break;
- }
-
- // Write delimiter
- if (!firstFile)
- {
- bytesLeft -= response->cat(',');
- }
- firstFile = false;
-
- // Write another file entry
- bytesLeft -= response->catf("{\"type\":\"%c\",\"name\":", fileInfo.isDirectory ? 'd' : 'f');
- bytesLeft -= response->EncodeString(fileInfo.fileName, MaxFilenameLength, false);
- bytesLeft -= response->catf(",\"size\":%" PRIu32, fileInfo.size);
-
- 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);
- }
- }
-
- // If there is no error, don't append "err":0 because if we do then DWC thinks there has been an error - looks like it doesn't check the value
- if (err != 0)
- {
- response->catf("],\"err\":%u}", err);
- }
- else
- {
- response->cat("]}");
- }
-
- return response;
-}
-
// Send a beep. We send it to both PanelDue and the web interface.
void RepRap::Beep(unsigned int freq, unsigned int ms)
{
diff --git a/src/RepRap.h b/src/RepRap.h
index 213adde3..64d2d459 100644
--- a/src/RepRap.h
+++ b/src/RepRap.h
@@ -101,8 +101,8 @@ public:
OutputBuffer *GetStatusResponse(uint8_t type, ResponseSource source);
OutputBuffer *GetConfigResponse();
OutputBuffer *GetLegacyStatusResponse(uint8_t type, int seq);
- OutputBuffer *GetFilesResponse(const char* dir, bool flagsDirs);
- OutputBuffer *GetFilelistResponse(const char* dir);
+ OutputBuffer *GetFilesResponse(const char* dir, unsigned int startAt, bool flagsDirs);
+ OutputBuffer *GetFilelistResponse(const char* dir, unsigned int startAt);
bool GetFileInfoResponse(const char *filename, OutputBuffer *&response, bool quitEarly);
void Beep(unsigned int freq, unsigned int ms);
diff --git a/src/Storage/FileStore.cpp b/src/Storage/FileStore.cpp
index 1a3b25e7..07322cb9 100644
--- a/src/Storage/FileStore.cpp
+++ b/src/Storage/FileStore.cpp
@@ -77,7 +77,7 @@ bool FileStore::Open(const char* directory, const char* fileName, OpenMode mode)
filePath[i] = 0;
if (!reprap.GetPlatform().GetMassStorage()->DirectoryExists(filePath.GetRef()) && !reprap.GetPlatform().GetMassStorage()->MakeDirectory(filePath.c_str()))
{
- reprap.GetPlatform().MessageF(ErrorMessage, "Failed to create directory %s while trying to open file %s\n", filePath.c_str(), location.c_str());
+ reprap.GetPlatform().MessageF(ErrorMessage, "Failed to create folder %s while trying to open file %s\n", filePath.c_str(), location.c_str());
return false;
}
filePath[i] = '/';
@@ -102,7 +102,7 @@ bool FileStore::Open(const char* directory, const char* fileName, OpenMode mode)
// It is up to the caller to report an error if necessary.
if (reprap.Debug(modulePlatform))
{
- reprap.GetPlatform().MessageF(ErrorMessage, "Can't open %s to %s, error code %d\n", location.c_str(), (writing) ? "write" : "read", openReturn);
+ reprap.GetPlatform().MessageF(ErrorMessage, "Can't open %s to %s, error code %d\n", location.c_str(), (writing) ? "write" : "read", (int)openReturn);
}
return false;
}
@@ -286,7 +286,7 @@ int FileStore::Read(char* extBuf, size_t nBytes)
FRESULT readStatus = f_read(&file, extBuf, nBytes, &bytes_read);
if (readStatus != FR_OK)
{
- reprap.GetPlatform().Message(ErrorMessage, "Cannot read file.\n");
+ reprap.GetPlatform().MessageF(ErrorMessage, "Cannot read file, error code %d.\n", (int)readStatus);
return -1;
}
return (int)bytes_read;
@@ -397,7 +397,7 @@ bool FileStore::Write(const char *s, size_t len)
if ((writeStatus != FR_OK) || (totalBytesWritten != len))
{
- reprap.GetPlatform().Message(ErrorMessage, "Failed to write to file. Drive may be full.\n");
+ reprap.GetPlatform().MessageF(ErrorMessage, "Failed to write to file, error code %d. Card may be full.\n", (int)writeStatus);
return false;
}
return true;
@@ -432,7 +432,7 @@ bool FileStore::Flush()
if ((writeStatus != FR_OK) || (bytesToWrite != bytesWritten))
{
- reprap.GetPlatform().Message(ErrorMessage, "Failed to write to file. Drive may be full.\n");
+ reprap.GetPlatform().MessageF(ErrorMessage, "Failed to flush data to file, error code %d. Card may be full.\n", (int)writeStatus);
return false;
}
}
diff --git a/src/Version.h b/src/Version.h
index 0a6ddc9e..6c5ebe24 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -18,11 +18,11 @@
# define RTOSVER
#endif
-# define VERSION MAIN_VERSION RTOSVER "RC6"
+# define VERSION MAIN_VERSION RTOSVER
#endif
#ifndef DATE
-# define DATE "2018-05-29b4"
+# define DATE "2018-06-05b3"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman"