From 0e8056390595d0336a8e747070687427a5d464a4 Mon Sep 17 00:00:00 2001 From: David Crocker Date: Tue, 8 Nov 2016 16:21:43 +0000 Subject: Version 1.16 release Added I parameter in M280 command Added diagnostic test (M122 S101) for SX1509B chip on Duet WiFi expansion boards Heaters driven from TC channels on Duet WiFi no longer glitch on for a short while after reset Bug fix: M280 S-1 was ignoring inverted output status Bug fix: if there were too many files in the /gcodes folder then AJAX errors occurred (thanks chrishamm) --- src/Configuration.h | 7 ++++-- src/DuetNG/DueXn.cpp | 13 ++++++++-- src/DuetNG/DueXn.h | 1 + src/DuetNG/SX1509.cpp | 12 ++++++++- src/GCodes/GCodes.cpp | 9 ++++++- src/Heating/Pid.cpp | 2 +- src/OutputMemory.cpp | 67 ++++++++++++++++++--------------------------------- src/OutputMemory.h | 9 +++---- src/Platform.cpp | 6 +++++ src/Platform.h | 5 +++- src/Reprap.cpp | 4 +-- 11 files changed, 77 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/Configuration.h b/src/Configuration.h index 9d809ed4..42e01f49 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.16rc3" +# define VERSION "1.16" #endif #ifndef DATE -# define DATE "2016-11-06" +# define DATE "2016-11-08" #endif #define AUTHORS "reprappro, dc42, zpl, t3p3, dnewman" @@ -155,11 +155,14 @@ const size_t FILENAME_LENGTH = 100; #ifdef DUET_NG const uint16_t OUTPUT_BUFFER_SIZE = 256; // How many bytes does each OutputBuffer hold? const size_t OUTPUT_BUFFER_COUNT = 32; // How many OutputBuffer instances do we have? +const size_t RESERVED_OUTPUT_BUFFERS = 1; // Number of reserved output buffers after long responses. Must be enough for an HTTP header #else const uint16_t OUTPUT_BUFFER_SIZE = 128; // How many bytes does each OutputBuffer hold? const size_t OUTPUT_BUFFER_COUNT = 32; // How many OutputBuffer instances do we have? +const size_t RESERVED_OUTPUT_BUFFERS = 2; // Number of reserved output buffers after long responses. Must be enough for an HTTP header #endif + // Move system const float DEFAULT_FEEDRATE = 3000.0; // The initial requested feed rate after resetting the printer diff --git a/src/DuetNG/DueXn.cpp b/src/DuetNG/DueXn.cpp index ac6f0785..c89d50b0 100644 --- a/src/DuetNG/DueXn.cpp +++ b/src/DuetNG/DueXn.cpp @@ -72,8 +72,7 @@ namespace DuetExpansion expander.pinModeMultiple(AllFanBits, OUTPUT_PWM); // Initialise the PWM pins 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 + expander.pinModeMultiple(stopBits | AllGpioBits, INPUT); // Initialise the endstop inputs and GPIO pins (no pullups because 5V-tolerant) // Set up the interrupt on any input change inputMask = stopBits | AllGpioBits; @@ -170,6 +169,16 @@ namespace DuetExpansion expander.analogWrite(pin, (uint8_t)(constrain(pwm, 0.0, 1.0) * 255)); } } + + // Diagnose the SX1509 by setting all pins as inputs and reading them + uint16_t DiagnosticRead() + { + expander.pinModeMultiple(AllStopBitsX5 | AllGpioBits | AllFanBits, INPUT); // Initialise the endstop inputs and GPIO pins (no pullups because 5V-tolerant) + delay(1); + const uint16_t retval = expander.digitalReadAll(); // read all inputs with pullup resistors on fans + Init(); // back to normal + return retval; + } } // end namespace // End diff --git a/src/DuetNG/DueXn.h b/src/DuetNG/DueXn.h index 312620ec..e943b116 100644 --- a/src/DuetNG/DueXn.h +++ b/src/DuetNG/DueXn.h @@ -27,6 +27,7 @@ namespace DuetExpansion bool DigitalRead(Pin pin); // Read a pin void DigitalWrite(Pin pin, bool high); // Write a pin void AnalogOut(Pin pin, float pwm); // Set the PWM value on this pin + uint16_t DiagnosticRead(); // Diagnose the SX1509 by setting all pins as inputs and reading them }; #endif /* SRC_DUETNG_DUEXN_H_ */ diff --git a/src/DuetNG/SX1509.cpp b/src/DuetNG/SX1509.cpp index 7837a1d5..98035cca 100644 --- a/src/DuetNG/SX1509.cpp +++ b/src/DuetNG/SX1509.cpp @@ -87,24 +87,31 @@ void SX1509::pinModeMultiple(uint16_t pins, PinMode inOut) switch (inOut) { case INPUT: + clearBitsInWord(REG_LED_DRIVER_ENABLE_B, pins); + clearBitsInWord(REG_INPUT_DISABLE_B, pins); setBitsInWord(REG_DIR_B, pins); clearBitsInWord(REG_PULL_UP_B, pins); clearBitsInWord(REG_PULL_DOWN_B, pins); break; case INPUT_PULLUP: + clearBitsInWord(REG_LED_DRIVER_ENABLE_B, pins); + clearBitsInWord(REG_INPUT_DISABLE_B, pins); setBitsInWord(REG_DIR_B, pins); - setBitsInWord(REG_PULL_UP_B, pins); clearBitsInWord(REG_PULL_DOWN_B, pins); + setBitsInWord(REG_PULL_UP_B, pins); break; case INPUT_PULLDOWN: + clearBitsInWord(REG_LED_DRIVER_ENABLE_B, pins); + clearBitsInWord(REG_INPUT_DISABLE_B, pins); setBitsInWord(REG_DIR_B, pins); clearBitsInWord(REG_PULL_UP_B, pins); setBitsInWord(REG_PULL_DOWN_B, pins); break; case OUTPUT_LOW: + clearBitsInWord(REG_LED_DRIVER_ENABLE_B, pins); clearBitsInWord(REG_PULL_UP_B, pins); clearBitsInWord(REG_PULL_DOWN_B, pins); clearBitsInWord(REG_DATA_B, pins); @@ -113,6 +120,7 @@ void SX1509::pinModeMultiple(uint16_t pins, PinMode inOut) break; case OUTPUT_HIGH: + clearBitsInWord(REG_LED_DRIVER_ENABLE_B, pins); clearBitsInWord(REG_PULL_UP_B, pins); clearBitsInWord(REG_PULL_DOWN_B, pins); setBitsInWord(REG_DATA_B, pins); @@ -121,6 +129,7 @@ void SX1509::pinModeMultiple(uint16_t pins, PinMode inOut) break; case OUTPUT_LOW_OPEN_DRAIN: + clearBitsInWord(REG_LED_DRIVER_ENABLE_B, pins); clearBitsInWord(REG_PULL_UP_B, pins); clearBitsInWord(REG_PULL_DOWN_B, pins); clearBitsInWord(REG_DATA_B, pins); @@ -129,6 +138,7 @@ void SX1509::pinModeMultiple(uint16_t pins, PinMode inOut) break; case OUTPUT_HIGH_OPEN_DRAIN: + clearBitsInWord(REG_LED_DRIVER_ENABLE_B, pins); clearBitsInWord(REG_PULL_UP_B, pins); clearBitsInWord(REG_PULL_DOWN_B, pins); setBitsInWord(REG_DATA_B, pins); diff --git a/src/GCodes/GCodes.cpp b/src/GCodes/GCodes.cpp index c65b0d01..771daa2d 100644 --- a/src/GCodes/GCodes.cpp +++ b/src/GCodes/GCodes.cpp @@ -4181,13 +4181,20 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply) bool invert; if (platform->GetFirmwarePin(servoIndex, PinAccess::servo, servoPin, invert)) { + if (gb->Seen('I')) + { + if (gb->GetIValue() > 0) + { + invert = !invert; + } + } if (gb->Seen('S')) { float angleOrWidth = gb->GetFValue(); if (angleOrWidth < 0.0) { // Disable the servo by setting the pulse width to zero - Platform::WriteAnalog(servoPin, 0.0, ServoRefreshFrequency); + Platform::WriteAnalog(servoPin, (invert) ? 1.0 : 0.0, ServoRefreshFrequency); } else { diff --git a/src/Heating/Pid.cpp b/src/Heating/Pid.cpp index e1a8190c..836d009f 100644 --- a/src/Heating/Pid.cpp +++ b/src/Heating/Pid.cpp @@ -786,7 +786,7 @@ void PID::FitCurve() void PID::DisplayBuffer(const char *intro) { OutputBuffer *buf; - if (OutputBuffer::Allocate(buf, false)) + if (OutputBuffer::Allocate(buf)) { buf->catf("%s: interval %.1f sec, readings", intro, tuningReadingInterval * MillisToSeconds); for (size_t i = 0; i < tuningReadingsTaken; ++i) diff --git a/src/OutputMemory.cpp b/src/OutputMemory.cpp index 3e187814..b907cfa3 100644 --- a/src/OutputMemory.cpp +++ b/src/OutputMemory.cpp @@ -86,37 +86,34 @@ const char *OutputBuffer::Read(size_t len) return data + offset; } -int OutputBuffer::printf(const char *fmt, ...) +size_t OutputBuffer::printf(const char *fmt, ...) { char formatBuffer[FORMAT_STRING_LENGTH]; va_list vargs; va_start(vargs, fmt); - int ret = vsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs); + vsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs); va_end(vargs); - copy(formatBuffer); - return ret; + return copy(formatBuffer); } -int OutputBuffer::vprintf(const char *fmt, va_list vargs) +size_t OutputBuffer::vprintf(const char *fmt, va_list vargs) { char formatBuffer[FORMAT_STRING_LENGTH]; - int res = vsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs); + vsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs); - cat(formatBuffer); - return res; + return cat(formatBuffer); } -int OutputBuffer::catf(const char *fmt, ...) +size_t OutputBuffer::catf(const char *fmt, ...) { char formatBuffer[FORMAT_STRING_LENGTH]; va_list vargs; va_start(vargs, fmt); - int ret = vsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs); + vsnprintf(formatBuffer, ARRAY_SIZE(formatBuffer), fmt, vargs); va_end(vargs); - cat(formatBuffer); - return ret; + return cat(formatBuffer); } size_t OutputBuffer::copy(const char c) @@ -157,7 +154,7 @@ size_t OutputBuffer::copy(const char *src, size_t len) OutputBuffer *currentBuffer; size_t bytesCopied = OUTPUT_BUFFER_SIZE; do { - if (!Allocate(currentBuffer, true)) + if (!Allocate(currentBuffer)) { // We cannot store the whole string, stop here break; @@ -207,7 +204,7 @@ size_t OutputBuffer::cat(const char c) { // No - allocate a new item and copy the data OutputBuffer *nextBuffer; - if (!Allocate(nextBuffer, true)) + if (!Allocate(nextBuffer)) { // We cannot store any more data. Should never happen return 0; @@ -247,7 +244,7 @@ size_t OutputBuffer::cat(const char *src, size_t len) { // Yes - copy what we couldn't write into a new chain OutputBuffer *nextBuffer; - if (!Allocate(nextBuffer, true)) + if (!Allocate(nextBuffer)) { // We cannot store any more data, stop here return copyLength; @@ -360,7 +357,7 @@ size_t OutputBuffer::EncodeReply(OutputBuffer *src, bool allowControlChars) } // Allocates an output buffer instance which can be used for (large) string outputs -/*static*/ bool OutputBuffer::Allocate(OutputBuffer *&buf, bool isAppending) +/*static*/ bool OutputBuffer::Allocate(OutputBuffer *&buf) { const irqflags_t flags = cpu_irq_save(); @@ -372,18 +369,6 @@ size_t OutputBuffer::EncodeReply(OutputBuffer *src, bool allowControlChars) buf = nullptr; return false; } - else if (isAppending) - { - // It's a good idea to leave at least one OutputBuffer available if we're - // writing a large chunk of data... - if (freeOutputBuffers->next == nullptr) - { - cpu_irq_restore(flags); - - buf = nullptr; - return false; - } - } buf = freeOutputBuffers; freeOutputBuffers = buf->next; @@ -407,32 +392,28 @@ size_t OutputBuffer::EncodeReply(OutputBuffer *src, bool allowControlChars) // Get the number of bytes left for continuous writing /*static*/ size_t OutputBuffer::GetBytesLeft(const OutputBuffer *writingBuffer) { - // If writingBuffer is NULL, just return how much space there is left for continuous writing + size_t freeOutputBuffers = OUTPUT_BUFFER_COUNT - usedOutputBuffers; if (writingBuffer == nullptr) { - if (usedOutputBuffers == OUTPUT_BUFFER_COUNT) - { - // No more instances can be allocated - return 0; - } - - return (OUTPUT_BUFFER_COUNT - usedOutputBuffers - 1) * OUTPUT_BUFFER_SIZE; + // Only return the total number of bytes left + return freeOutputBuffers * OUTPUT_BUFFER_SIZE; } - // Do we have any more buffers left for writing? - if (usedOutputBuffers == OUTPUT_BUFFER_COUNT) + // We're doing a possibly long response like a filelist + size_t bytesLeft = OUTPUT_BUFFER_SIZE - writingBuffer->last->DataLength(); + + if (freeOutputBuffers < RESERVED_OUTPUT_BUFFERS) { - // No - refer to this one only - return OUTPUT_BUFFER_SIZE - writingBuffer->last->DataLength(); + // Keep some space left to encapsulate the respones (e.g. via an HTTP header) + return bytesLeft; } - // Yes - we know how many buffers are in use, so there is no need to work through the free list - return (OUTPUT_BUFFER_SIZE - writingBuffer->last->DataLength() + (OUTPUT_BUFFER_COUNT - usedOutputBuffers - 1) * OUTPUT_BUFFER_SIZE); + return bytesLeft + (freeOutputBuffers - RESERVED_OUTPUT_BUFFERS) * OUTPUT_BUFFER_SIZE; } // Truncate an output buffer to free up more memory. Returns the number of released bytes. -/*static */ size_t OutputBuffer::Truncate(OutputBuffer *buffer, size_t bytesNeeded ) +/*static */ size_t OutputBuffer::Truncate(OutputBuffer *buffer, size_t bytesNeeded) { // Can we free up space from this chain? Don't break it up if it's referenced anywhere else if (buffer == nullptr || buffer->Next() == nullptr || buffer->IsReferenced()) diff --git a/src/OutputMemory.h b/src/OutputMemory.h index 8106f974..629fbe4f 100644 --- a/src/OutputMemory.h +++ b/src/OutputMemory.h @@ -39,9 +39,9 @@ class OutputBuffer const char *Read(size_t len); size_t BytesLeft() const { return dataLength - bytesRead; } // How many bytes have not been sent yet? - int printf(const char *fmt, ...); - int vprintf(const char *fmt, va_list vargs); - int catf(const char *fmt, ...); + size_t printf(const char *fmt, ...); + size_t vprintf(const char *fmt, va_list vargs); + size_t catf(const char *fmt, ...); size_t copy(const char c); size_t copy(const char *src); @@ -61,8 +61,7 @@ class OutputBuffer static void Init(); // Allocate an unused OutputBuffer instance. Returns true on success or false if no instance could be allocated. - // Setting isAppending to true will guarantee that one OutputBuffer will remain available for single allocation. - static bool Allocate(OutputBuffer *&buf, bool isAppending = false); + static bool Allocate(OutputBuffer *&buf); // Get the number of bytes left for allocation. If writingBuffer is not NULL, this returns the number of free bytes for // continuous writes, i.e. for writes that need to allocate an extra OutputBuffer instance to finish the message. diff --git a/src/Platform.cpp b/src/Platform.cpp index bbbf0573..20409663 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -1507,6 +1507,12 @@ void Platform::DiagnosticTest(int d) DDA::PrintMoves(); break; +#ifdef DUET_NG + case (int)DiagnosticTestType::PrintExpanderStatus: + MessageF(GENERIC_MESSAGE, "Expander status %04X\n", DuetExpansion::DiagnosticRead()); + break; +#endif + default: break; } diff --git a/src/Platform.h b/src/Platform.h index e5ce5480..94ea54bc 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -236,7 +236,10 @@ enum class DiagnosticTestType : int TestWatchdog = 1001, // test that we get a watchdog reset if the tick interrupt stops TestSpinLockup = 1002, // test that we get a software reset if a Spin() function takes too long TestSerialBlock = 1003, // test what happens when we write a blocking message via debugPrintf() - PrintMoves = 100 // print summary of recent moves + PrintMoves = 100, // print summary of recent moves +#ifdef DUET_NG + PrintExpanderStatus = 101, // print DueXn expander status +#endif }; // Enumeration to describe what we want to do with a logical pin diff --git a/src/Reprap.cpp b/src/Reprap.cpp index a0a9300e..6b39b3ff 100644 --- a/src/Reprap.cpp +++ b/src/Reprap.cpp @@ -896,14 +896,14 @@ OutputBuffer *RepRap::GetStatusResponse(uint8_t type, ResponseSource source) if (source == ResponseSource::AUX) { - OutputBuffer *response = platform->GetAuxGCodeReply(); + OutputBuffer *reply = platform->GetAuxGCodeReply(); if (response != nullptr) { // Send the response to the last command. Do this last response->catf(",\"seq\":%u,\"resp\":", platform->GetAuxSeq()); // send the response sequence number // Send the JSON response - response->EncodeReply(response, true); // also releases the OutputBuffer chain + response->EncodeReply(reply, true); // also releases the OutputBuffer chain } } response->cat("}"); -- cgit v1.2.3