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>2017-02-08 13:45:24 +0300
committerDavid Crocker <dcrocker@eschertech.com>2017-02-08 13:45:37 +0300
commit8f6d8e9da77f8442d7f8e05d6362ddfac8e43b8f (patch)
tree43ea73fe63aa03eda541f5038591eb7e9c80742b /src
parentf35c8cb759c7c4400494d9b39fefd378c5a5cc66 (diff)
Version 1.17d+1
Save several words of stsck after a hard fault and print them in the M122 software reset report Increased the maximum step frequency before the firmware switches to double stepping Added diagnostic test for timing the square root calculation Minor firmware optimisations
Diffstat (limited to 'src')
-rw-r--r--src/Libraries/Math/Isqrt.cpp7
-rw-r--r--src/Movement/DDA.cpp6
-rw-r--r--src/Movement/DDA.h13
-rw-r--r--src/Movement/DriveMovement.cpp52
-rw-r--r--src/Platform.cpp49
-rw-r--r--src/Platform.h23
-rw-r--r--src/RepRapFirmware.cpp2
-rw-r--r--src/Version.h4
-rw-r--r--src/Webserver/Webserver.cpp40
9 files changed, 110 insertions, 86 deletions
diff --git a/src/Libraries/Math/Isqrt.cpp b/src/Libraries/Math/Isqrt.cpp
index 4feb0d96..3c8bb990 100644
--- a/src/Libraries/Math/Isqrt.cpp
+++ b/src/Libraries/Math/Isqrt.cpp
@@ -1,8 +1,5 @@
#include "RepRapFirmware.h"
-// The remaining functions are speed-critical, so use full optimisation
-#pragma GCC optimize ("O3")
-
// Fast 62-bit integer square root function (thanks dmould)
uint32_t isqrt64(uint64_t num)
{
@@ -58,7 +55,7 @@ uint32_t isqrt64(uint64_t num)
iter64a(14) iter64a(12) iter64a(10) iter64a(8)
iter64a(6) iter64a(4) iter64a(2) iter64a(0)
- // resHigh is twice the square root of the msw, in the range 0..2^17-1
+ // resHigh is twice the square root of the msw, in the range 0..2^16-1 with the input restricted to 62 bits
uint64_t numAll = ((uint64_t)numHigh << 32) | (uint32_t)num;
#define iter64b(N) \
@@ -74,7 +71,7 @@ uint32_t isqrt64(uint64_t num)
// We need to do 16 iterations.
// After the last iteration, numAll may be between 0 and (1 + 2 * res) inclusive.
- // So to take square roots of numbers up to 64 bits, we need to do all these iterations using 64 bit maths.
+ // So to take square roots of numbers up to 62 bits, we need to do all these iterations using 64 bit maths.
// If we restricted the input to e.g. 48 bits, then we could do some of the final iterations using 32-bit maths.
iter64b(30) iter64b(28) iter64b(26) iter64b(24)
iter64b(22) iter64b(20) iter64b(18) iter64b(16)
diff --git a/src/Movement/DDA.cpp b/src/Movement/DDA.cpp
index 74d614c2..9afd2b1e 100644
--- a/src/Movement/DDA.cpp
+++ b/src/Movement/DDA.cpp
@@ -838,9 +838,9 @@ void DDA::Prepare()
dm.nextStepTime = 0;
dm.stepInterval = 999999; // initialise to a large value so that we will calculate the time for just one step
dm.stepsTillRecalc = 0; // so that we don't skip the calculation
- bool stepsToDo = (isDeltaMovement && drive < numAxes)
- ? dm.CalcNextStepTimeDelta(*this, false)
- : dm.CalcNextStepTimeCartesian(*this, false);
+ const bool stepsToDo = (isDeltaMovement && drive < numAxes)
+ ? dm.CalcNextStepTimeDelta(*this, false)
+ : dm.CalcNextStepTimeCartesian(*this, false);
if (stepsToDo)
{
InsertDM(&dm);
diff --git a/src/Movement/DDA.h b/src/Movement/DDA.h
index 1756c181..4ba65436 100644
--- a/src/Movement/DDA.h
+++ b/src/Movement/DDA.h
@@ -68,21 +68,22 @@ public:
void DebugPrint() const;
- static const uint32_t stepClockRate = VARIANT_MCK/32; // the frequency of the clock used for stepper pulse timing, about 0.38us resolution on the Duet
+ static const uint32_t stepClockRate = VARIANT_MCK/128; // the frequency of the clock used for stepper pulse timing (see Platform::InitialiseInterrupts)
static const uint64_t stepClockRateSquared = (uint64_t)stepClockRate * stepClockRate;
// Note on the following constant:
// If we calculate the step interval on every clock, we reach a point where the calculation time exceeds the step interval.
// The worst case is pure Z movement on a delta. On a Mini Kossel with 80 steps/mm with this firmware running on a Duet (84MHx SAM3X8 processor),
// the calculation can just be managed in time at speeds of 15000mm/min (step interval 50us), but not at 20000mm/min (step interval 37.5us).
- // Therefore, where the step interval falls below 70us, we don't calculate on every step.
+ // Therefore, where the step interval falls below 60us, we don't calculate on every step.
+ // Note: the above measurements were taken some time ago, before some firmware optimisations.
#ifdef DUET_NG
- static const int32_t MinCalcIntervalDelta = (50 * stepClockRate)/1000000; // the smallest sensible interval between calculations (70us) in step timer clocks
- static const int32_t MinCalcIntervalCartesian = (50 * stepClockRate)/1000000; // same as delta for now, but could be lower
+ static const int32_t MinCalcIntervalDelta = (40 * stepClockRate)/1000000; // the smallest sensible interval between calculations (40us) in step timer clocks
+ static const int32_t MinCalcIntervalCartesian = (40 * stepClockRate)/1000000; // same as delta for now, but could be lower
static const uint32_t minInterruptInterval = 6; // about 2us minimum interval between interrupts, in clocks
#else
- static const int32_t MinCalcIntervalDelta = (70 * stepClockRate)/1000000; // the smallest sensible interval between calculations (70us) in step timer clocks
- static const int32_t MinCalcIntervalCartesian = (70 * stepClockRate)/1000000; // same as delta for now, but could be lower
+ static const int32_t MinCalcIntervalDelta = (60 * stepClockRate)/1000000; // the smallest sensible interval between calculations (60us) in step timer clocks
+ static const int32_t MinCalcIntervalCartesian = (60 * stepClockRate)/1000000; // same as delta for now, but could be lower
static const uint32_t minInterruptInterval = 6; // about 2us minimum interval between interrupts, in clocks
#endif
diff --git a/src/Movement/DriveMovement.cpp b/src/Movement/DriveMovement.cpp
index 1b052f2b..eebd6524 100644
--- a/src/Movement/DriveMovement.cpp
+++ b/src/Movement/DriveMovement.cpp
@@ -199,7 +199,7 @@ bool DriveMovement::CalcNextStepTimeCartesianFull(const DDA &dda, bool live)
pre(nextStep < totalSteps; stepsTillRecalc == 0)
{
// Work out how many steps to calculate at a time.
- uint32_t shiftFactor;
+ uint32_t shiftFactor = 0; // assume single stepping
if (stepInterval < DDA::MinCalcIntervalCartesian)
{
uint32_t stepsToLimit = ((nextStep <= reverseStartStep && reverseStartStep <= totalSteps)
@@ -218,19 +218,12 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
{
shiftFactor = 1; // double stepping
}
- else
- {
- shiftFactor = 0; // single stepping
- }
- }
- else
- {
- shiftFactor = 0; // single stepping
}
+
stepsTillRecalc = (1u << shiftFactor) - 1u; // store number of additional steps to generate
- uint32_t nextCalcStep = nextStep + stepsTillRecalc;
- uint32_t lastStepTime = nextStepTime; // pick up the time of the last step
+ const uint32_t nextCalcStep = nextStep + stepsTillRecalc;
+ const uint32_t lastStepTime = nextStepTime; // pick up the time of the last step
if (nextCalcStep < mp.cart.accelStopStep)
{
// acceleration phase
@@ -244,7 +237,7 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
else if (nextCalcStep < reverseStartStep)
{
// deceleration phase, not reversed yet
- uint64_t temp = mp.cart.twoCsquaredTimesMmPerStepDivA * nextCalcStep;
+ const uint64_t temp = mp.cart.twoCsquaredTimesMmPerStepDivA * nextCalcStep;
// Allow for possible rounding error when the end speed is zero or very small
nextStepTime = (twoDistanceToStopTimesCsquaredDivA > temp)
? topSpeedTimesCdivAPlusDecelStartClocks - isqrt64(twoDistanceToStopTimesCsquaredDivA - temp)
@@ -273,7 +266,7 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
// When the end speed is very low, calculating the time of the last step is very sensitive to rounding error.
// So if this is the last step and it is late, bring it forward to the expected finish time.
// Very rarely on a delta, the penultimate step may also be calculated late. Allow for that here in case it affects Cartesian axes too.
- if (nextStep == totalSteps || nextStep + 1 == totalSteps)
+ if (nextStep + 1 >= totalSteps)
{
nextStepTime = dda.clocksNeeded;
}
@@ -295,7 +288,7 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
{
// Work out how many steps to calculate at a time.
// The simulator suggests that at 200steps/mm, the minimum step pulse interval for 400mm/sec movement is 4.5us
- uint32_t shiftFactor;
+ uint32_t shiftFactor = 0; // assume single stepping
if (stepInterval < DDA::MinCalcIntervalDelta)
{
const uint32_t stepsToLimit = ((nextStep < reverseStartStep && reverseStartStep <= totalSteps)
@@ -318,15 +311,8 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
{
shiftFactor = 1; // double stepping
}
- else
- {
- shiftFactor = 0; // single stepping
- }
- }
- else
- {
- shiftFactor = 0; // single stepping
}
+
stepsTillRecalc = (1u << shiftFactor) - 1; // store number of additional steps to generate
if (nextStep == reverseStartStep)
@@ -339,19 +325,19 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
}
// Calculate d*s*K as an integer, where d = distance the head has travelled, s = steps/mm for this drive, K = a power of 2 to reduce the rounding errors
- if (direction)
- {
- mp.delta.hmz0sK += (int32_t)(K2 << shiftFactor);
- }
- else
{
- mp.delta.hmz0sK -= (int32_t)(K2 << shiftFactor);
+ int32_t shiftedK2 = (int32_t)(K2 << shiftFactor);
+ if (!direction)
+ {
+ shiftedK2 = -shiftedK2;
+ }
+ mp.delta.hmz0sK += shiftedK2;
}
const int32_t hmz0scK = (int32_t)(((int64_t)mp.delta.hmz0sK * dda.cKc)/Kc);
const int32_t t1 = mp.delta.minusAaPlusBbTimesKs + hmz0scK;
// Due to rounding error we can end up trying to take the square root of a negative number if we do not take precautions here
- const int64_t t2a = (int64_t)isquare64(t1) + mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared - (int64_t)isquare64(mp.delta.hmz0sK);
+ const int64_t t2a = mp.delta.dSquaredMinusAsquaredMinusBsquaredTimesKsquaredSsquared - (int64_t)isquare64(mp.delta.hmz0sK) + (int64_t)isquare64(t1);
const int32_t t2 = (t2a > 0) ? isqrt64(t2a) : 0;
const int32_t dsK = (direction) ? t1 - t2 : t1 + t2;
@@ -363,7 +349,7 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
return false;
}
- uint32_t lastStepTime = nextStepTime; // pick up the time of the last step
+ const uint32_t lastStepTime = nextStepTime; // pick up the time of the last step
if ((uint32_t)dsK < mp.delta.accelStopDsK)
{
// Acceleration phase
@@ -376,7 +362,7 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
}
else
{
- uint64_t temp = (uint64_t)mp.delta.twoCsquaredTimesMmPerStepDivAK * (uint32_t)dsK;
+ const uint64_t temp = (uint64_t)mp.delta.twoCsquaredTimesMmPerStepDivAK * (uint32_t)dsK;
// Because of possible rounding error when the end speed is zero or very small, we need to check that the square root will work OK
nextStepTime = (temp < twoDistanceToStopTimesCsquaredDivA)
? topSpeedTimesCdivAPlusDecelStartClocks - isqrt64(twoDistanceToStopTimesCsquaredDivA - temp)
@@ -391,13 +377,13 @@ pre(nextStep < totalSteps; stepsTillRecalc == 0)
// When the end speed is very low, calculating the time of the last step is very sensitive to rounding error.
// So if this is the last step and it is late, bring it forward to the expected finish time.
// Very rarely, the penultimate step may be calculated late, so allow for that too.
- if (nextStep == totalSteps || nextStep + 1 == totalSteps)
+ if (nextStep + 1 >= totalSteps)
{
nextStepTime = dda.clocksNeeded;
}
else
{
- // We don't expect any step except the last to be late
+ // We don't expect any steps except the last two to be late
state = DMState::stepError;
stepInterval = 10000000 + nextStepTime; // so we can tell what happened in the debug print
return false;
diff --git a/src/Platform.cpp b/src/Platform.cpp
index 7199ff04..06b3b6b8 100644
--- a/src/Platform.cpp
+++ b/src/Platform.cpp
@@ -27,6 +27,7 @@
#include "Network.h"
#include "RepRap.h"
#include "Webserver.h"
+#include "Libraries/Math/Isqrt.h"
#include "sam/drivers/tc/tc.h"
#include "sam/drivers/hsmci/hsmci.h"
@@ -145,8 +146,7 @@ extern "C"
// Also get the program counter when the exception occurred.
void prvGetRegistersFromStack(const uint32_t *pulFaultStackAddress)
{
- const uint32_t pc = pulFaultStackAddress[6];
- reprap.GetPlatform()->SoftwareReset((uint16_t)SoftwareResetReason::hardFault, pc);
+ reprap.GetPlatform()->SoftwareReset((uint16_t)SoftwareResetReason::hardFault, pulFaultStackAddress + 6);
}
// The fault handler implementation calls a function called prvGetRegistersFromStack()
@@ -1219,7 +1219,8 @@ void Platform::Spin()
ClassReport(longWait);
}
-void Platform::SoftwareReset(uint16_t reason, uint32_t pc)
+// Perform a software reset. 'stk' points to the program counter on the stack if the cause is an exception, otherwise it is nullptr.
+void Platform::SoftwareReset(uint16_t reason, const uint32_t *stk)
{
wdt_restart(WDT); // kick the watchdog
if (reason == (uint16_t)SoftwareResetReason::erase)
@@ -1280,7 +1281,14 @@ void Platform::SoftwareReset(uint16_t reason, uint32_t pc)
GetStackUsage(NULL, NULL, &srdBuf[slot].neverUsedRam);
srdBuf[slot].hfsr = SCB->HFSR;
srdBuf[slot].cfsr = SCB->CFSR;
- srdBuf[slot].pc = pc;
+ srdBuf[slot].icsr = SCB->ICSR;
+ if (stk != nullptr)
+ {
+ for (size_t i = 0; i < ARRAY_SIZE(srdBuf[slot].stack); ++i)
+ {
+ srdBuf[slot].stack[i] = stk[i];
+ }
+ }
// Save diagnostics data to Flash
#ifdef DUET_NG
@@ -1331,10 +1339,10 @@ void Platform::InitialiseInterrupts()
// Timer interrupt for stepper motors
// The clock rate we use is a compromise. Too fast and the 64-bit square roots take a long time to execute. Too slow and we lose resolution.
- // We choose a clock divisor of 32, which gives us 0.38us resolution. The next option is 128 which would give 1.524us resolution.
+ // We choose a clock divisor of 128 which gives 1.524us resolution on the Duet 085 (84MHz clock) and 0.9375us resolution on the Duet WiFi.
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t) STEP_TC_IRQN);
- tc_init(STEP_TC, STEP_TC_CHAN, TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK3);
+ tc_init(STEP_TC, STEP_TC_CHAN, TC_CMR_WAVE | TC_CMR_WAVSEL_UP | TC_CMR_TCCLKS_TIMER_CLOCK4);
STEP_TC->TC_CHANNEL[STEP_TC_CHAN].TC_IDR = ~(uint32_t)0; // interrupts disabled for now
tc_start(STEP_TC, STEP_TC_CHAN);
tc_get_status(STEP_TC, STEP_TC_CHAN); // clear any pending interrupt
@@ -1445,9 +1453,15 @@ void Platform::Diagnostics(MessageType mtype)
Message(mtype, "Last software reset code ");
if (slot >= 0 && srdBuf[slot].magic == SoftwareResetData::magicValue)
{
- MessageF(mtype, "0x%04x, PC 0x%08x, HFSR 0x%08x, CFSR 0x%08x, available RAM %u bytes (slot %d)\n",
- srdBuf[slot].resetReason, srdBuf[slot].pc, srdBuf[slot].hfsr, srdBuf[slot].cfsr, srdBuf[slot].neverUsedRam, slot);
- MessageF(mtype, "Spinning module during software reset: %s\n", moduleName[srdBuf[slot].resetReason & 0x0F]);
+ scratchString.Clear();
+ for (size_t i = 0; i < ARRAY_SIZE(srdBuf[slot].stack); ++i)
+ {
+ scratchString.catf(" %08x", srdBuf[slot].stack[i]);
+ }
+ MessageF(mtype, "0x%04x, HFSR 0x%08x, CFSR 0x%08x, ICSR 0x%08x\nStack:%s\n",
+ srdBuf[slot].resetReason, srdBuf[slot].hfsr, srdBuf[slot].cfsr, srdBuf[slot].icsr, scratchString.Pointer());
+ MessageF(mtype, "Spinning module during software reset: %s, available RAM %u bytes (slot %d)\n",
+ moduleName[srdBuf[slot].resetReason & 0x0F], srdBuf[slot].neverUsedRam, slot);
}
else
{
@@ -1583,6 +1597,23 @@ void Platform::DiagnosticTest(int d)
DDA::PrintMoves();
break;
+ case (int)DiagnosticTestType::TimeSquareRoot: // Show the square root calculation time. The displayed value is subject to interrupts.
+ {
+ const uint32_t num1 = 0x7265ac3d;
+ const uint32_t now1 = Platform::GetInterruptClocks();
+ const uint32_t num1a = isqrt64((uint64_t)num1 * num1);
+ const uint32_t tim1 = Platform::GetInterruptClocks() - now1;
+
+ const uint32_t num2 = 0x0000a4c5;
+ const uint32_t now2 = Platform::GetInterruptClocks();
+ const uint32_t num2a = isqrt64((uint64_t)num2 * num2);
+ const uint32_t tim2 = Platform::GetInterruptClocks() - now2;
+ MessageF(GENERIC_MESSAGE, "Square roots: 64-bit %.1fus %s, 32-bit %.1fus %s\n",
+ (float)(tim1 * 1000000)/DDA::stepClockRate, (num1a == num1) ? "ok" : "ERROR",
+ (float)(tim2 * 1000000)/DDA::stepClockRate, (num2a == num2) ? "ok" : "ERROR");
+ }
+ break;
+
#ifdef DUET_NG
case (int)DiagnosticTestType::PrintExpanderStatus:
MessageF(GENERIC_MESSAGE, "Expander status %04X\n", DuetExpansion::DiagnosticRead());
diff --git a/src/Platform.h b/src/Platform.h
index f887f907..52f7d453 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -180,6 +180,7 @@ enum class DiagnosticTestType : int
#ifdef DUET_NG
PrintExpanderStatus = 101, // print DueXn expander status
#endif
+ TimeSquareRoot = 102 // do a timing test on the square roor function
};
// Enumeration to describe what we want to do with a logical pin
@@ -326,7 +327,7 @@ public:
void ClassReport(float &lastTime); // Called on Spin() return to check everything's live.
void LogError(ErrorCode e) { errorCodeBits |= (uint32_t)e; }
- void SoftwareReset(uint16_t reason, uint32_t pc = 0);
+ void SoftwareReset(uint16_t reason, const uint32_t *stk = nullptr);
bool AtxPower() const;
void SetAtxPower(bool on);
void SetBoardType(BoardType bt);
@@ -609,22 +610,30 @@ private:
// directly from/to flash memory.
struct SoftwareResetData
{
- static const uint16_t versionValue = 4; // increment this whenever this struct changes
+ static const uint16_t versionValue = 6; // increment this whenever this struct changes
static const uint16_t magicValue = 0x7D00 | versionValue; // value we use to recognise that all the flash data has been written
- static const uint32_t nvAddress = 0; // must be 4-byte aligned
- static const size_t numberOfSlots = 8; // number of storage slots used to implement wear levelling
+ static const size_t numberOfSlots = 6; // number of storage slots used to implement wear levelling
uint16_t magic; // the magic number, including the version
uint16_t resetReason; // this records why we did a software reset, for diagnostic purposes
uint32_t neverUsedRam; // the amount of never used RAM at the last abnormal software reset
uint32_t hfsr; // hard fault status register
uint32_t cfsr; // configurable fault status register
- uint32_t pc; // program counter when the exception occurred
+ uint32_t icsr; // interrupt control and state register
+ uint32_t stack[16]; // stack when the exception occurred, with the program counter at the bottom
bool isVacant() const // return true if this struct can be written without erasing it first
{
- return magic == 0xFFFF && resetReason == 0xFFFF && neverUsedRam == 0xFFFFFFFF
- && hfsr == 0xFFFFFFFF && cfsr == 0xFFFFFFFF && pc == 0xFFFFFFFF;
+ const uint32_t *p = reinterpret_cast<const uint32_t*>(this);
+ for (size_t i = 0; i < sizeof(*this)/sizeof(uint32_t); ++i)
+ {
+ if (*p != 0xFFFFFFFF)
+ {
+ return false;
+ }
+ ++p;
+ }
+ return true;
}
};
diff --git a/src/RepRapFirmware.cpp b/src/RepRapFirmware.cpp
index 9a09fbd3..97ea7f37 100644
--- a/src/RepRapFirmware.cpp
+++ b/src/RepRapFirmware.cpp
@@ -186,7 +186,7 @@ const char *moduleName[] =
// Utilities and storage not part of any class
-static char scratchStringBuffer[140]; // this is now used only for short messages; needs to be long enough to print delta parameters
+static char scratchStringBuffer[150]; // this is now used only for short messages; needs to be long enough to print delta parameters and 12 words of stack (132 bytes)
StringRef scratchString(scratchStringBuffer, ARRAY_SIZE(scratchStringBuffer));
// For debug use
diff --git a/src/Version.h b/src/Version.h
index 51ed7b46..fa8bf2e9 100644
--- a/src/Version.h
+++ b/src/Version.h
@@ -9,11 +9,11 @@
#define SRC_VERSION_H_
#ifndef VERSION
-# define VERSION "1.17d"
+# define VERSION "1.17d+1"
#endif
#ifndef DATE
-# define DATE "2017-01-28"
+# define DATE "2017-02-01"
#endif
#define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman"
diff --git a/src/Webserver/Webserver.cpp b/src/Webserver/Webserver.cpp
index 9c11c4bc..620e6246 100644
--- a/src/Webserver/Webserver.cpp
+++ b/src/Webserver/Webserver.cpp
@@ -343,32 +343,32 @@ uint16_t Webserver::GetGCodeBufferSpace(const WebSource source) const
void Webserver::ConnectionLost(Connection conn)
{
// Inform protocol handlers that this connection has been lost
- uint16_t localPort = Network::GetLocalPort(conn);
+ const uint16_t localPort = Network::GetLocalPort(conn);
ProtocolInterpreter *interpreter;
switch (localPort)
{
- case FTP_PORT: /* FTP */
- interpreter = ftpInterpreter;
- break;
+ case FTP_PORT: /* FTP */
+ interpreter = ftpInterpreter;
+ break;
- case TELNET_PORT: /* Telnet */
- interpreter = telnetInterpreter;
- break;
+ case TELNET_PORT: /* Telnet */
+ interpreter = telnetInterpreter;
+ break;
- default: /* HTTP and FTP data */
- if (localPort == network->GetHttpPort())
- {
- interpreter = httpInterpreter;
- break;
- }
- else if (localPort == network->GetDataPort())
- {
- interpreter = ftpInterpreter;
- break;
- }
+ default: /* HTTP and FTP data */
+ if (localPort == network->GetHttpPort())
+ {
+ interpreter = httpInterpreter;
+ break;
+ }
+ else if (localPort == network->GetDataPort())
+ {
+ interpreter = ftpInterpreter;
+ break;
+ }
- platform->MessageF(GENERIC_MESSAGE, "Error: Webserver should handle disconnect event at local port %d, but no handler was found!\n", localPort);
- return;
+ platform->MessageF(GENERIC_MESSAGE, "Error: Webserver should handle disconnect event at local port %d, but no handler was found!\n", localPort);
+ return;
}
// Print some debug information and notify the protocol interpreter