Version 1.09a

Merged in zpl's latest changes to Network and Print Monitor modules,
providing DHCP and Netbios name support
Added command M999 S4321 to unlock flash memory, reset and boot to BOSSA
port
Z dive height is now relative to Z probe trigger height and default is
reduced to 3mm
Added experimental support for acoustic probe for delta printers
Bug fix: firmware once again prevents Z homing before X and Y are homed,
if the Z probe is used for Z homing
Various code tidying
This commit is contained in:
David Crocker 2015-05-17 21:06:39 +01:00
parent 7d11c9e217
commit 4cc0a512b4
26 changed files with 1285 additions and 542 deletions

View file

@ -24,8 +24,8 @@ Licence: GPL
#define CONFIGURATION_H
#define NAME "RepRapFirmware"
#define VERSION "1.04g-dc42"
#define DATE "2015-04-20"
#define VERSION "1.09a-dc42"
#define DATE "2015-05-17"
#define AUTHORS "reprappro, dc42, zpl"
#define FLASH_SAVE_ENABLED (1)
@ -77,7 +77,7 @@ const float DefaultFeedRate = 3000; // The initial requested feed rate after
const size_t MaxProbePoints = 16; // Maximum number of probe points
const size_t MaxDeltaCalibrationPoints = 16; // Must be <= MaxProbePoints, may be smaller to reduce matrix storage requirements. Preferably a power of 2.
const float DefaultZDive = 5.0; // Default height from which to probe the bed (mm)
const float DefaultZDive = 3.0; // Default height from which to probe the bed (mm)
#define TRIANGLE_0 -0.001 // Slightly less than 0 for point-in-triangle tests

10
DDA.cpp
View file

@ -730,12 +730,12 @@ bool DDA::Step()
// because we have both a high endstop and a Z probe, and the Z motor is not the same thing as the Z axis.
switch (reprap.GetPlatform()->GetZProbeResult())
{
case lowHit:
case EndStopHit::lowHit:
MoveAborted(now); // set the state to completed and recalculate the endpoints
reprap.GetMove()->ZProbeTriggered(this);
break;
case lowNear:
case EndStopHit::lowNear:
ReduceHomingSpeed(reprap.GetPlatform()->ConfiguredInstantDv(Z_AXIS));
break;
@ -757,7 +757,7 @@ bool DDA::Step()
{
switch(reprap.GetPlatform()->Stopped(drive))
{
case lowHit:
case EndStopHit::lowHit:
endStopsToCheck &= ~(1 << drive); // clear this check so that we can check for more
if (endStopsToCheck == 0) // if no more endstops to check
{
@ -770,7 +770,7 @@ bool DDA::Step()
reprap.GetMove()->HitLowStop(drive, this);
break;
case highHit:
case EndStopHit::highHit:
endStopsToCheck &= ~(1 << drive); // clear this check so that we can check for more
if (endStopsToCheck == 0) // if no more endstops to check
{
@ -783,7 +783,7 @@ bool DDA::Step()
reprap.GetMove()->HitHighStop(drive, this);
break;
case lowNear:
case EndStopHit::lowNear:
// Only reduce homing speed if there are no more axes to be homed.
// This allows us to home X and Y simultaneously.
if (endStopsToCheck == (1 << drive))

248
DeltaParameters.cpp Normal file
View file

@ -0,0 +1,248 @@
/*
* DeltaParameters.cpp
*
* Created on: 20 Apr 2015
* Author: David
*/
#include "RepRapFirmware.h"
void DeltaParameters::Init()
{
deltaMode = false;
diagonal = 0.0;
radius = 0.0;
printRadius = defaultPrintRadius;
homedHeight = defaultDeltaHomedHeight;
isEquilateral = true;
for (size_t axis = 0; axis < AXES; ++axis)
{
endstopAdjustments[axis] = 0.0;
towerX[axis] = towerY[axis] = 0.0;
}
}
void DeltaParameters::SetRadius(float r)
{
radius = r;
isEquilateral = true;
const float cos30 = sqrtf(3.0)/2.0;
const float sin30 = 0.5;
towerX[A_AXIS] = -(r * cos30);
towerX[B_AXIS] = r * cos30;
towerX[C_AXIS] = 0.0;
towerY[A_AXIS] = towerY[B_AXIS] = -(r * sin30);
towerY[C_AXIS] = r;
Recalc();
}
void DeltaParameters::Recalc()
{
deltaMode = (radius > 0.0 && diagonal > radius);
if (deltaMode)
{
Xbc = towerX[C_AXIS] - towerX[B_AXIS];
Xca = towerX[A_AXIS] - towerX[C_AXIS];
Xab = towerX[B_AXIS] - towerX[A_AXIS];
Ybc = towerY[C_AXIS] - towerY[B_AXIS];
Yca = towerY[A_AXIS] - towerY[C_AXIS];
Yab = towerY[B_AXIS] - towerY[A_AXIS];
coreFa = fsquare(towerX[A_AXIS]) + fsquare(towerY[A_AXIS]);
coreFb = fsquare(towerX[B_AXIS]) + fsquare(towerY[B_AXIS]);
coreFc = fsquare(towerX[C_AXIS]) + fsquare(towerY[C_AXIS]);
Q = 2 * (Xca * Yab - Xab * Yca);
Q2 = fsquare(Q);
D2 = fsquare(diagonal);
// Calculate the base carriage height when the printer is homed.
const float tempHeight = diagonal; // any sensible height will do here, probably even zero
float machinePos[AXES];
InverseTransform(tempHeight + endstopAdjustments[X_AXIS], tempHeight + endstopAdjustments[Y_AXIS], tempHeight + endstopAdjustments[X_AXIS],
machinePos);
homedCarriageHeight = homedHeight + tempHeight - machinePos[Z_AXIS];
}
}
// Make the average of the endstop adjustments zero, without changing the individual homed carriage heights
void DeltaParameters::NormaliseEndstopAdjustments()
{
const float eav = (endstopAdjustments[A_AXIS] + endstopAdjustments[B_AXIS] + endstopAdjustments[C_AXIS])/3.0;
endstopAdjustments[A_AXIS] -= eav;
endstopAdjustments[B_AXIS] -= eav;
endstopAdjustments[C_AXIS] -= eav;
homedHeight += eav;
homedCarriageHeight += eav; // no need for a full recalc, this is sufficient
}
// Calculate the motor position for a single tower from a Cartesian coordinate
float DeltaParameters::Transform(const float machinePos[AXES], size_t axis) const
{
return machinePos[Z_AXIS]
+ sqrt(D2 - fsquare(machinePos[X_AXIS] - towerX[axis]) - fsquare(machinePos[Y_AXIS] - towerY[axis]));
}
void DeltaParameters::InverseTransform(float Ha, float Hb, float Hc, float machinePos[AXES]) const
{
const float Fa = coreFa + fsquare(Ha);
const float Fb = coreFb + fsquare(Hb);
const float Fc = coreFc + fsquare(Hc);
// debugPrintf("Ha=%f Hb=%f Hc=%f Fa=%f Fb=%f Fc=%f Xbc=%f Xca=%f Xab=%f Ybc=%f Yca=%f Yab=%f\n",
// Ha, Hb, Hc, Fa, Fb, Fc, Xbc, Xca, Xab, Ybc, Yca, Yab);
// Setup PQRSU such that x = -(S - uz)/P, y = (P - Rz)/Q
const float P = (Xbc * Fa) + (Xca * Fb) + (Xab * Fc);
const float S = (Ybc * Fa) + (Yca * Fb) + (Yab * Fc);
const float R = 2 * ((Xbc * Ha) + (Xca * Hb) + (Xab * Hc));
const float U = 2 * ((Ybc * Ha) + (Yca * Hb) + (Yab * Hc));
// debugPrintf("P= %f R=%f S=%f U=%f Q=%f\n", P, R, S, U, Q);
const float R2 = fsquare(R), U2 = fsquare(U);
float A = U2 + R2 + Q2;
float minusHalfB = S * U + P * R + Ha * Q2 + towerX[A_AXIS] * U * Q - towerY[A_AXIS] * R * Q;
float C = fsquare(S + towerX[A_AXIS] * Q) + fsquare(P - towerY[A_AXIS] * Q) + (fsquare(Ha) - D2) * Q2;
// debugPrintf("A=%f minusHalfB=%f C=%f\n", A, minusHalfB, C);
float z = (minusHalfB - sqrtf(fsquare(minusHalfB) - A * C)) / A;
machinePos[X_AXIS] = (U * z - S) / Q;
machinePos[Y_AXIS] = (P - R * z) / Q;
machinePos[Z_AXIS] = z;
}
// Compute the derivative of height with respect to a parameter at the specified motor endpoints.
// 'deriv' indicates the parameter as follows:
// 0, 1, 2 = X, Y, Z tower endstop adjustments
// 3, 4 = X, Y tower X position
// 5 = Z tower Y position
// 6 = diagonal rod length
// 7 = delta radius (only if isEquilateral is true)
float DeltaParameters::ComputeDerivative(unsigned int deriv, float ha, float hb, float hc)
{
const float perturb = 0.2; // perturbation amount in mm
DeltaParameters hiParams(*this), loParams(*this);
switch(deriv)
{
case 0:
case 1:
case 2:
break;
case 3:
case 4:
hiParams.towerX[deriv - 3] += perturb;
loParams.towerX[deriv - 3] -= perturb;
break;
case 5:
{
const float yAdj = perturb * (1.0/3.0);
hiParams.towerY[A_AXIS] -= yAdj;
hiParams.towerY[B_AXIS] -= yAdj;
hiParams.towerY[C_AXIS] += (perturb - yAdj);
loParams.towerY[A_AXIS] += yAdj;
loParams.towerY[B_AXIS] += yAdj;
loParams.towerY[C_AXIS] -= (perturb - yAdj);
}
break;
case 6:
hiParams.diagonal += perturb;
loParams.diagonal -= perturb;
break;
case 7:
hiParams.SetRadius(radius + perturb);
loParams.SetRadius(radius - perturb);
break;
}
hiParams.Recalc();
loParams.Recalc();
float newPos[AXES];
hiParams.InverseTransform((deriv == 0) ? ha + perturb : ha, (deriv == 1) ? hb + perturb : hb, (deriv == 2) ? hc + perturb : hc, newPos);
float zHi = newPos[Z_AXIS];
loParams.InverseTransform((deriv == 0) ? ha - perturb : ha, (deriv == 1) ? hb - perturb : hb, (deriv == 2) ? hc - perturb : hc, newPos);
float zLo = newPos[Z_AXIS];
return (zHi - zLo)/(2 * perturb);
}
// Perform 3, 4, 6 or 7-factor adjustment.
// The input vector contains the following parameters in this order:
// X, Y and Z endstop adjustments
// If we are doing 4-factor adjustment, the next argument is the delta radius. Otherwise:
// X tower X position adjustment
// Y tower X position adjustment
// Z tower Y position adjustment
// Diagonal rod length adjustment
void DeltaParameters::Adjust(size_t numFactors, const float v[])
{
const float oldCarriageHeightA = GetHomedCarriageHeight(A_AXIS); // save for later
// Update endstop adjustments
endstopAdjustments[A_AXIS] += v[0];
endstopAdjustments[B_AXIS] += v[1];
endstopAdjustments[C_AXIS] += v[2];
NormaliseEndstopAdjustments();
if (numFactors == 4)
{
// 4-factor adjustment, so update delta radius
SetRadius(radius + v[3]); // this sets isEquilateral true, recalculates tower positions, then calls Recalc()
}
else if (numFactors > 3)
{
// 6- or 7-factor adjustment
towerX[A_AXIS] += v[3];
towerX[B_AXIS] += v[4];
const float yAdj = v[5] * (1.0/3.0);
towerY[A_AXIS] -= yAdj;
towerY[B_AXIS] -= yAdj;
towerY[C_AXIS] += (v[5] - yAdj);
isEquilateral = false;
if (numFactors == 7)
{
diagonal += v[6];
}
Recalc();
}
// Adjusting the diagonal and the tower positions affects the homed carriage height.
// We need to adjust homedHeight to allow for this, to get the change that was requested in the endstop corrections.
const float heightError = GetHomedCarriageHeight(A_AXIS) - oldCarriageHeightA - v[0];
homedHeight -= heightError;
homedCarriageHeight -= heightError;
}
void DeltaParameters::PrintParameters(StringRef& reply, bool full)
{
reply.printf("Endstops X%.2f Y%.2f Z%.2f, height %.2f, diagonal %.2f, ",
endstopAdjustments[A_AXIS], endstopAdjustments[B_AXIS], endstopAdjustments[C_AXIS], homedHeight, diagonal);
if (isEquilateral && !full)
{
reply.catf("radius %.2f\n", radius);
}
else
{
reply.catf("towers (%.2f,%.2f) (%.2f,%.2f) (%.2f,%.2f)\n",
towerX[A_AXIS], towerY[A_AXIS], towerX[B_AXIS], towerY[B_AXIS], towerX[C_AXIS], towerY[C_AXIS]);
}
}
// End

67
DeltaParameters.h Normal file
View file

@ -0,0 +1,67 @@
/*
* DeltaParameters.h
*
* Created on: 20 Apr 2015
* Author: David
*/
#ifndef DELTAPARAMETERS_H_
#define DELTAPARAMETERS_H_
// Class to hold the parameter for a delta machine.
// Some of the values that are currently calculated on demand could be pre-calculated in Recalc() and stored instead.
class DeltaParameters
{
public:
DeltaParameters() { Init(); }
bool IsDeltaMode() const { return deltaMode; }
bool IsEquilateral() const { return isEquilateral; }
float GetDiagonal() const { return diagonal; }
float GetRadius() const { return radius; }
float GetPrintRadius() const { return printRadius; }
float GetTowerX(size_t axis) const { return towerX[axis]; }
float GetTowerY(size_t axis) const { return towerY[axis]; }
float GetEndstopAdjustment(size_t axis) const { return endstopAdjustments[axis]; }
float GetHomedCarriageHeight(size_t axis) const { return homedCarriageHeight + endstopAdjustments[axis]; }
float GetPrintRadiusSquared() const { return printRadiusSquared; }
void Init();
void SetDiagonal(float d) { diagonal = d; Recalc(); }
void SetRadius(float r);
void SetEndstopAdjustment(size_t axis, float x) { endstopAdjustments[axis] = x; }
void SetPrintRadius(float r) { printRadius = r; printRadiusSquared = r * r; }
float GetHomedHeight() const { return homedHeight; }
void SetHomedHeight(float h) { homedHeight = h; Recalc(); }
float Transform(const float machinePos[AXES], size_t axis) const; // Calculate the motor position for a single tower from a Cartesian coordinate
void InverseTransform(float Ha, float Hb, float Hc, float machinePos[AXES]) const; // Calculate the Cartesian position from the motor positions
float ComputeDerivative(unsigned int deriv, float ha, float hb, float hc); // Compute the derivative of height with respect to a parameter at a set of motor endpoints
void Adjust(size_t numFactors, const float v[]); // Perform 4-, 6- or 7-factor adjustment
void PrintParameters(StringRef& reply, bool full);
private:
void Recalc();
void NormaliseEndstopAdjustments(); // Make the average of the endstop adjustments zero
// Core parameters
float diagonal; // The diagonal rod length, all 3 are assumed to be the same length
float radius; // The nominal delta radius, before any fine tuning of tower positions
float towerX[AXES]; // The X coordinate of each tower
float towerY[AXES]; // The Y coordinate of each tower
float endstopAdjustments[AXES]; // How much above or below the ideal position each endstop is
float printRadius;
float homedHeight;
// Derived values
bool deltaMode; // True if this is a delta printer
bool isEquilateral; // True if the towers are at the corners of an equilateral triangle
float printRadiusSquared;
float homedCarriageHeight;
float Xbc, Xca, Xab, Ybc, Yca, Yab;
float coreFa, coreFb, coreFc;
float Q, Q2, D2;
};
#endif /* DELTAPARAMETERS_H_ */

136
DeltaProbe.cpp Normal file
View file

@ -0,0 +1,136 @@
/*
* DeltaProbe.cpp
*
* Created on: 20 Apr 2015
* Author: David
*/
#include "RepRapFirmware.h"
// Set up to probe
bool DeltaProbe::Init(float frequency, float amplitude, float rate, float height)
{
debugPrintf("Start probe f=%.1f a=%.2f r=%.2f h=%.1f\n", frequency, amplitude, rate, height);
// Sanity check the inputs (we check the max amplitude later)
if (frequency < 50.0 || frequency > 1000.0 || amplitude < 0.02 || rate < 0.1 || rate > 10.0 || height < 0.5)
{
return false;
}
debugPrintf("ok so far\n");
// Calculate the number of steps for the peak to peak amplitude
const float zRate = reprap.GetPlatform()->DriveStepsPerUnit(Z_AXIS);
normalSteps = (size_t)(amplitude * zRate);
if (normalSteps > MaxSteps)
{
return false;
}
debugPrintf("normalSteps=%u\n", normalSteps);
// Build the tables of step times for sinusoidal motion
const float recipOmega = (float)DDA::stepClockRate/(frequency * 2.0 * PI);
for (size_t i = 0; i < normalSteps - 1; ++i)
{
normalStepTable[i] = acos(1.0 - (float)(2 * (i + 1))/(float)normalSteps) * recipOmega;
}
for (size_t i = 0; i < normalSteps; ++i)
{
incStepTable[i] = acos(1.0 - (float)(2 * (i + 1))/(float)(normalSteps + 1)) * recipOmega;
}
halfCycleTime = (uint32_t)((float)DDA::stepClockRate/(2.0 * frequency));
incStepTable[normalSteps] = normalStepTable[normalSteps - 1] = halfCycleTime;
halfCyclesPerIncrement = 2 * (unsigned int)((frequency / (rate * zRate)) + 0.5);
if (halfCyclesPerIncrement < 4)
{
halfCyclesPerIncrement = 4;
}
maxIncrements = height * zRate;
const float peakAccel = fsquare(2.0 * PI * frequency) * amplitude * 0.5;
debugPrintf("halfCycleTime=%u halfCyclesPerIncrement=%u peak accel=%.1f\n", halfCycleTime, halfCyclesPerIncrement, peakAccel);
debugPrintf("normalTable=");
for (unsigned int i = 0; i < normalSteps; ++i)
{
debugPrintf(" %u", normalStepTable[i]);
}
debugPrintf(" incStepTable=");
for (unsigned int i = 0; i <= normalSteps; ++i)
{
debugPrintf(" %u", incStepTable[i]);
}
debugPrintf("\n");
return true;
}
// Start probing, and return the time that the next step is due
uint32_t DeltaProbe::Start()
{
// Initialise the dynamic values
stepsDone = 0;
halfCycleCount = 0;
numIncrements = 0;
incrementing = false;
state = State::normal;
return normalStepTable[0];
}
bool DeltaProbe::GetDirection() const
{
return (halfCycleCount & 1) ? FORWARDS : BACKWARDS;
}
// Calculate the next step time. Returns 0xFFFFFFFF to stop.
uint32_t DeltaProbe::CalcNextStepTime()
{
if (state == State::stopped || state == State::overran)
{
return 0xFFFFFFFF;
}
++stepsDone;
if (stepsDone == ((incrementing) ? normalSteps + 1 : normalSteps))
{
stepsDone = 0;
++halfCycleCount;
if (state == State::stopping && (halfCycleCount & 1) == 0)
{
state = State::stopped;
return 0xFFFFFFFF;
}
if (incrementing)
{
++numIncrements;
incrementing = false;
}
if (halfCycleCount == halfCyclesPerIncrement)
{
if (numIncrements == maxIncrements)
{
state = State::overran; // another increment is due, but we have already gone down as far as we were asked to
return 0xFFFFFFFF;
}
halfCycleCount = 0;
incrementing = true;
}
}
return (incrementing)
? (halfCyclesPerIncrement * numIncrements * halfCycleTime) + incStepTable[stepsDone]
: (halfCyclesPerIncrement * numIncrements * halfCycleTime) + normalStepTable[stepsDone];
}
void DeltaProbe::Trigger()
{
if (state == State::normal)
{
state = State::stopping;
}
}
// End

44
DeltaProbe.h Normal file
View file

@ -0,0 +1,44 @@
/*
* DeltaProbe.h
*
* Created on: 20 Apr 2015
* Author: David
*/
#ifndef DELTAPROBE_H_
#define DELTAPROBE_H_
// Class to hold the parameters for my new Z probing method
class DeltaProbe
{
enum class State { normal, stopping, stopped, overran };
// Fixed parameters
static const unsigned int MaxSteps = 30; // 15 corresponds to 0.375mm p-p movement @ 80 steps/mm
// Static parameters, set up before we start probing and unchanged during probing
unsigned int normalSteps; // the number of steps we use to achieve the requested amplitude
unsigned int halfCyclesPerIncrement; // how many half cycles between lowering the head by 1 step
unsigned int maxIncrements; // max number of steps we lower the head
uint32_t halfCycleTime; // how many interrupt clocks per quarter cycle
uint32_t normalStepTable[MaxSteps]; // table of step times for the first half cycle, in interrupt clocks from start
uint32_t incStepTable[MaxSteps + 1]; // table of step times for the first half cycle, when we are moving down a step
// Dynamic parameters, to track the progress of the probe
unsigned int stepsDone; // how many steps since the start of this quarter cycle
unsigned int halfCycleCount; // how many quarter cycles since we started or lowered the head
unsigned int numIncrements; // how many steps we have lowered the head since we started
bool incrementing; // true if we are lowering the head 2 step in this half cycle
State state; // what state the probe is in
public:
bool Init(float frequency, float amplitude, float rate, float height); // Get ready to probe
uint32_t Start(); // start the process, return the next step time
bool GetDirection() const; // get the direction for the current step
uint32_t CalcNextStepTime(); // calculate when the next step is due
void Trigger(); // cease probing
bool Finished() const { return state == State::stopped || state == State::overran; }
bool Overran() const { return state == State::overran; }
};
#endif /* DELTAPROBE_H_ */

View file

@ -152,6 +152,7 @@ void GCodes::DoFilePrint(GCodeBuffer* gb, StringRef& reply)
else if (AllMovesAreFinishedAndMoveBufferIsLoaded())
{
fileBeingPrinted.Close();
reprap.GetPrintMonitor()->StoppedPrint();
}
break;
}
@ -170,7 +171,7 @@ void GCodes::Spin()
// Check for M105 poll requests from Pronterface and PanelDue so that the status is kept up to date during execution of file macros etc.
// No need to read multiple characters at a time in this case because the polling rate is quite low.
if (!serialGCode->Active() && serialGCode->WritingFileDirectory() == nullptr
&& (platform->GetLine()->Status() & byteAvailable))
&& (platform->GetLine()->Status() & (uint8_t)IOStatus::byteAvailable))
{
char b;
platform->GetLine()->Read(b);
@ -184,7 +185,7 @@ void GCodes::Spin()
}
}
if (!auxGCode->Active() && (platform->GetAux()->Status() & byteAvailable))
if (!auxGCode->Active() && (platform->GetAux()->Status() & (uint8_t)IOStatus::byteAvailable))
{
char b;
platform->GetAux()->Read(b);
@ -407,7 +408,7 @@ void GCodes::StartNextGCode(StringRef& reply)
// Now the serial interfaces.
if (platform->GetLine()->Status() & byteAvailable)
if (platform->GetLine()->Status() & (uint8_t)IOStatus::byteAvailable)
{
// First check the special case of uploading the reprap.htm file
if (serialGCode->WritingFileDirectory() == platform->GetWebDir())
@ -443,7 +444,7 @@ void GCodes::StartNextGCode(StringRef& reply)
break; // stop after receiving a complete gcode in case we haven't finished processing it
}
++i;
} while (i < 16 && (platform->GetLine()->Status() & byteAvailable));
} while (i < 16 && (platform->GetLine()->Status() & (uint8_t)IOStatus::byteAvailable));
platform->ClassReport(longWait);
return;
}
@ -451,7 +452,7 @@ void GCodes::StartNextGCode(StringRef& reply)
// Now run the G-Code buffers. It's important to fill up the G-Code buffers before we do this,
// otherwise we wouldn't have a chance to pause/cancel running prints.
if (!auxGCode->Active() && (platform->GetAux()->Status() & byteAvailable))
if (!auxGCode->Active() && (platform->GetAux()->Status() & (uint8_t)IOStatus::byteAvailable))
{
int8_t i = 0;
do
@ -465,7 +466,7 @@ void GCodes::StartNextGCode(StringRef& reply)
break; // stop after receiving a complete gcode in case we haven't finished processing it
}
++i;
} while (i < 16 && (platform->GetAux()->Status() & byteAvailable));
} while (i < 16 && (platform->GetAux()->Status() & (uint8_t)IOStatus::byteAvailable));
}
else if (webGCode->Active())
{
@ -949,7 +950,7 @@ bool GCodes::DoSingleZProbeAtPoint(int probePointIndex)
switch (cannedCycleMoveCount)
{
case 0: // Move Z to the dive height. This only does anything on the first move; on all the others Z is already there
moveToDo[Z_AXIS] = platform->GetZProbeDiveHeight();
moveToDo[Z_AXIS] = platform->GetZProbeDiveHeight() + max<float>(platform->ZProbeStopHeight(), 0.0);
activeDrive[Z_AXIS] = true;
moveToDo[DRIVES] = platform->MaxFeedrate(Z_AXIS);
activeDrive[DRIVES] = true;
@ -973,50 +974,50 @@ bool GCodes::DoSingleZProbeAtPoint(int probePointIndex)
return false;
case 2: // Probe the bed
if (!cannedCycleMoveQueued && reprap.GetPlatform()->GetZProbeResult() == lowHit)
{
// Z probe is already triggered at the start of the move, so abandon the probe and record an error
platform->Message(BOTH_ERROR_MESSAGE, "Z probe warning: probe already triggered at start of probing move\n");
cannedCycleMoveCount = 0;
reprap.GetMove()->SetZBedProbePoint(probePointIndex, platform->GetZProbeDiveHeight(), true, true);
return true;
}
const float height = (axisIsHomed[Z_AXIS])
? 2 * platform->GetZProbeDiveHeight() // Z axis has been homed, so no point in going very far
: 1.1 * platform->AxisTotalLength(Z_AXIS); // Z axis not homed yet, so treat this as a homing move
switch(DoZProbe(height))
{
case 0:
// Z probe is already triggered at the start of the move, so abandon the probe and record an error
platform->Message(BOTH_ERROR_MESSAGE, "Z probe warning: probe already triggered at start of probing move\n");
cannedCycleMoveCount++;
reprap.GetMove()->SetZBedProbePoint(probePointIndex, platform->GetZProbeDiveHeight(), true, true);
break;
moveToDo[Z_AXIS] = (axisIsHomed[Z_AXIS])
? -platform->GetZProbeDiveHeight() // Z axis has been homed, so no point in going very far
: -1.1 * platform->AxisTotalLength(Z_AXIS); // Z axis not homed yet, so treat this as a homing move
activeDrive[Z_AXIS] = true;
moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS);
activeDrive[DRIVES] = true;
if (DoCannedCycleMove(ZProbeActive))
{
// The head has been moved down until the probe was triggered. Get the height from the live coordinates.
// DoCannedCycleMove has already loaded the current position into moveBuffer
if (axisIsHomed[Z_AXIS])
{
lastProbedZ = moveBuffer[Z_AXIS] - platform->ZProbeStopHeight();
case 1:
if (axisIsHomed[Z_AXIS])
{
lastProbedZ = moveBuffer[Z_AXIS] - platform->ZProbeStopHeight();
}
else
{
// The Z axis has not yet been homed, so treat this probe as a homing move.
moveBuffer[Z_AXIS] = platform->ZProbeStopHeight();
SetPositions(moveBuffer);
axisIsHomed[Z_AXIS] = true;
lastProbedZ = 0.0;
}
reprap.GetMove()->SetZBedProbePoint(probePointIndex, lastProbedZ, true, false);
cannedCycleMoveCount++;
break;
default:
break;
}
else
{
// The Z axis has not yet been homed, so treat this probe as a homing move.
moveBuffer[Z_AXIS] = platform->ZProbeStopHeight();
SetPositions(moveBuffer);
axisIsHomed[Z_AXIS] = true;
lastProbedZ = 0.0;
}
cannedCycleMoveCount++;
}
return false;
case 3: // Raise the head back up to the dive height
moveToDo[Z_AXIS] = platform->GetZProbeDiveHeight();
moveToDo[Z_AXIS] = platform->GetZProbeDiveHeight() + max<float>(platform->ZProbeStopHeight(), 0.0);
activeDrive[Z_AXIS] = true;
moveToDo[DRIVES] = platform->MaxFeedrate(Z_AXIS);
activeDrive[DRIVES] = true;
if (DoCannedCycleMove(0))
{
cannedCycleMoveCount = 0;
reprap.GetMove()->SetZBedProbePoint(probePointIndex, lastProbedZ, true, false);
return true;
}
return false;
@ -1027,30 +1028,62 @@ bool GCodes::DoSingleZProbeAtPoint(int probePointIndex)
}
}
// This simply moves down till the Z probe/switch is triggered.
// This simply moves down till the Z probe/switch is triggered. Call it repeatedly until it returns true.
// Called when we do a G30 with no P parameter.
bool GCodes::DoSingleZProbe()
{
for (size_t drive = 0; drive <= DRIVES; drive++)
switch (DoZProbe(1.1 * platform->AxisTotalLength(Z_AXIS)))
{
activeDrive[drive] = false;
}
case 0: // failed
return true;
moveToDo[Z_AXIS] = -1.1 * platform->AxisTotalLength(Z_AXIS);
activeDrive[Z_AXIS] = true;
moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS);
activeDrive[DRIVES] = true;
if (DoCannedCycleMove(ZProbeActive))
{
// The head has been moved down until the probe was triggered. Get the height from the live coordinates.
// DoCannedCycleMove has already loaded the current position into moveBuffer
case 1: // success
moveBuffer[Z_AXIS] = platform->ZProbeStopHeight();
SetPositions(moveBuffer);
axisIsHomed[Z_AXIS] = true;
lastProbedZ = 0.0;
return true;
default: // not finished yet
return false;
}
}
// Do a Z probe cycle up to the maximum specified distance.
// Returns -1 if not complete yet
// Returns 0 if failed
// Returns 1 if success, with lastProbedZ set to the height we stopped at and the current position in moveBuffer
int GCodes::DoZProbe(float distance)
{
if (platform->GetZProbeType() == 5)
{
const ZProbeParameters& params = platform->GetZProbeParameters();
return reprap.GetMove()->DoDeltaProbe(params.param1, params.param2, platform->HomeFeedRate(Z_AXIS), distance);
}
else
{
if (!cannedCycleMoveQueued && reprap.GetPlatform()->GetZProbeResult() == EndStopHit::lowHit)
{
return 0;
}
// Do a normal canned cycle Z movement with Z probe enabled
for (size_t drive = 0; drive <= DRIVES; drive++)
{
activeDrive[drive] = false;
}
moveToDo[Z_AXIS] = -distance;
activeDrive[Z_AXIS] = true;
moveToDo[DRIVES] = platform->HomeFeedRate(Z_AXIS);
activeDrive[DRIVES] = true;
if (DoCannedCycleMove(ZProbeActive))
{
return 1;
}
return -1;
}
return false;
}
// This is called to execute a G30.
@ -1339,11 +1372,17 @@ void GCodes::WriteGCodeToFile(GCodeBuffer *gb)
// Set up a file to print, but don't print it yet.
void GCodes::QueueFileToPrint(const char* fileName)
{
fileToPrint.Close();
fileGCode->CancelPause(); // if we paused it and then asked to print a new file, cancel any pending command
FileStore *f = platform->GetFileStore(platform->GetGCodeDir(), fileName, false);
if (f != NULL)
{
// Cancel current print if there is any
if (PrintingAFile())
{
CancelPrint();
}
fileGCode->SetToolNumberAdjust(0); // clear tool number adjustment
// Reset all extruder positions when starting a new print
for (size_t extruder = AXES; extruder < DRIVES; extruder++)
{
@ -1351,10 +1390,6 @@ void GCodes::QueueFileToPrint(const char* fileName)
}
fileToPrint.Set(f);
if (!fileBeingPrinted.IsLive())
{
fileGCode->SetToolNumberAdjust(0); // clear tool number adjustment
}
}
else
{
@ -2092,9 +2127,21 @@ bool GCodes::HandleGcode(GCodeBuffer* gb, StringRef& reply)
if (toBeHomed == 0 || toBeHomed == ((1 << X_AXIS) | (1 << Y_AXIS) | (1 << Z_AXIS)))
{
// Homing everything
SetAllAxesNotHomed();
DoFileMacro(HOME_ALL_G);
}
else if ( platform->MustHomeXYBeforeZ()
&& ((toBeHomed & (1 << Z_AXIS)) != 0)
&& ( (((toBeHomed & (1 << X_AXIS)) == 0) && !axisIsHomed[X_AXIS])
|| (((toBeHomed & (1 << Y_AXIS)) == 0) && !axisIsHomed[Y_AXIS])
)
)
{
// We can only home Z if both X and Y have already been homed or are being homed
reply.copy("Must home X and Y before homing Z");
error = true;
}
else
{
state = GCodeState::homing;
@ -2215,6 +2262,9 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
isPaused = false;
reply.copy("Print cancelled\n");
}
// Reset everything
CancelPrint();
break;
case 18: // Motors off
@ -2332,10 +2382,10 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
{
const char* filename = gb->GetUnprecedentedString();
reprap.GetPrintMonitor()->StartingFilePrint(filename);
QueueFileToPrint(filename);
if (fileToPrint.IsLive())
{
reprap.GetPrintMonitor()->StartingPrint(filename);
if (platform->Emulating() == marlin && gb == serialGCode)
{
reply.copy("File opened\nFile selected\n");
@ -2349,7 +2399,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
if (code == 32)
{
fileBeingPrinted.MoveFrom(fileToPrint);
reprap.GetPrintMonitor()->StartedFilePrint();
reprap.GetPrintMonitor()->StartedPrint();
}
}
else
@ -2379,7 +2429,7 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
else
{
fileBeingPrinted.MoveFrom(fileToPrint);
reprap.GetPrintMonitor()->StartedFilePrint();
reprap.GetPrintMonitor()->StartedPrint();
}
break;
@ -2859,19 +2909,19 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
const char* es;
switch (platform->Stopped(axis))
{
case lowHit:
case EndStopHit::lowHit:
es = "at min stop";
break;
case highHit:
case EndStopHit::highHit:
es = "at max stop";
break;
case lowNear:
case EndStopHit::lowNear:
es = "near min stop";
break;
case noStop:
case EndStopHit::noStop:
default:
es = "not stopped";
}
@ -3522,10 +3572,31 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
seen = true;
}
if (gb->Seen('S'))
{
ZProbeParameters params = platform->GetZProbeParameters();
params.param1 = gb->GetFValue();
platform->SetZProbeParameters(params);
seen = true;
}
if (gb->Seen('T'))
{
ZProbeParameters params = platform->GetZProbeParameters();
params.param2 = gb->GetFValue();
platform->SetZProbeParameters(params);
seen = true;
}
if (!seen)
{
reply.printf("Z Probe type is %d on channel %d with dive height %.1f and it is used for these axes:",
platform->GetZProbeType(), platform->GetZProbeChannel(), platform->GetZProbeDiveHeight());
reply.printf("Z Probe type %d, channel %d, dive height %.1f", platform->GetZProbeType(), platform->GetZProbeChannel(), platform->GetZProbeDiveHeight());
if (platform->GetZProbeType() == 5)
{
ZProbeParameters params = platform->GetZProbeParameters();
reply.catf(", parameters %.2f %.2f", params.param1, params.param2);
}
reply.cat(", used for these axes:");
for (size_t axis = 0; axis < AXES; axis++)
{
if (zProbeAxes[axis])
@ -3773,8 +3844,8 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
bool logic;
platform->GetEndStopConfiguration(axis, config, logic);
reply.catf(" %c %s %s %c", axisLetters[axis],
(config == highEndStop) ? "high end" : (config == lowEndStop) ? "low end" : "none",
(config == noEndStop) ? "" : (logic) ? " (active high)" : " (active low)",
(config == EndStopType::highEndStop) ? "high end" : (config == EndStopType::lowEndStop) ? "low end" : "none",
(config == EndStopType::noEndStop) ? "" : (logic) ? " (active high)" : " (active low)",
(axis == AXES - 1) ? '\n' : ',');
}
}
@ -3996,7 +4067,10 @@ bool GCodes::HandleMcode(GCodeBuffer* gb, StringRef& reply)
result = DoDwellTime(0.5);// wait half a second to allow the response to be sent back to the web server, otherwise it may retry
if (result)
{
platform->SoftwareReset(SoftwareResetReason::user); // doesn't return
uint16_t reason = (gb->Seen('S') && gb->GetIValue() == 4321)
? SoftwareResetReason::erase
: SoftwareResetReason::user;
platform->SoftwareReset(reason); // doesn't return
}
break;
@ -4056,6 +4130,21 @@ void GCodes::PauseSDPrint()
}
}
// Cancel the current SD card print
void GCodes::CancelPrint()
{
moveAvailable = false;
fileGCode->Init();
if (fileBeingPrinted.IsLive())
{
fileBeingPrinted.Close();
}
reprap.GetPrintMonitor()->StoppedPrint();
}
// Return true if all the heaters for the specified tool are at their set temperatures
bool GCodes::ToolHeatersAtSetTemperatures(const Tool *tool) const
{

View file

@ -119,11 +119,13 @@ class GCodes
bool HandleGcode(GCodeBuffer* gb, StringRef& reply); // Do a G code
bool HandleMcode(GCodeBuffer* gb, StringRef& reply); // Do an M code
bool HandleTcode(GCodeBuffer* gb, StringRef& reply); // Do a T code
void CancelPrint(); // Cancel the current print
int SetUpMove(GCodeBuffer* gb, StringRef& reply); // Pass a move on to the Move module
bool DoDwell(GCodeBuffer *gb); // Wait for a bit
bool DoDwellTime(float dwell); // Really wait for a bit
bool DoSingleZProbeAtPoint(int probePointIndex); // Probe at a given point
bool DoSingleZProbe(); // Probe where we are
int DoZProbe(float distance); // Do a Z probe cycle up to the maximum specified distance
bool SetSingleZProbeAtAPosition(GCodeBuffer *gb, StringRef& reply); // Probes at a given position - see the comment at the head of the function itself
void SetBedEquationWithProbe(int sParam, StringRef& reply); // Probes a series of points and sets the bed equation
bool SetPrintZProbe(GCodeBuffer *gb, StringRef& reply); // Either return the probe value, or set its threshold
@ -232,8 +234,8 @@ inline bool GCodes::HaveIncomingData() const
{
return fileBeingPrinted.IsLive() ||
webserver->GCodeAvailable() ||
(platform->GetLine()->Status() & byteAvailable) ||
(platform->GetAux()->Status() & byteAvailable);
(platform->GetLine()->Status() & (uint8_t)IOStatus::byteAvailable) ||
(platform->GetAux()->Status() & (uint8_t)IOStatus::byteAvailable);
}
// This function takes care of the fact that the heater and head indices don't match because the bed is heater 0.

View file

@ -68,23 +68,13 @@
#include "lwip/src/include/netif/etharp.h"
#include "lwip/src/sam/include/netif/ethernetif.h"
#include "emac.h"
#include "include/emac.h"
extern void RepRapNetworkMessage(const char*);
/* Global variable containing MAC Config (hw addr, IP, GW, ...) */
struct netif gs_net_if;
//*****************************AB
//Pass through function for interface status
//by including ethernetif.h directly and calling ethernetif_phy_link_status(); this function is not required
bool status_link_up()
{
return ethernetif_phy_link_status();
}
//*****************************AB
struct netif* ethernet_get_configuration()
{
return &gs_net_if;
@ -193,10 +183,13 @@ static void ethernet_configure_interface(unsigned char ipAddress[], unsigned cha
/** \brief Initialize the Ethernet subsystem.
*
*/
void init_ethernet(void)
void init_ethernet(const u8_t macAddress[], const char *hostname)
{
lwip_init();
ethernet_hardware_init();
ethernetif_set_mac_address(macAddress);
netif_set_hostname(&gs_net_if, hostname);
}
/** \brief Try to establish a physical link at, returning true if successful.
@ -216,13 +209,6 @@ void start_ethernet(const unsigned char ipAddress[], const unsigned char netMask
ethernet_configure_interface(ipAddress, netMask, gateWay);
}
/** \brief Set the DHCP hostname.
*
*/
void set_dhcp_hostname(const char *hostname)
{
gs_net_if.hostname = hostname;
}
//*************************************************************************************************************
/**
@ -237,7 +223,7 @@ void ethernet_status_callback(struct netif *netif)
{
RepRapNetworkMessage("Network up, IP=");
ipaddr_ntoa_r(&(netif->ip_addr), c_mess, sizeof(c_mess));
strncat(c_mess, sizeof(c_mess) - strlen(c_mess) - 1, "\n");
strncat(c_mess, sizeof(c_mess) - 1, "\n");
RepRapNetworkMessage(c_mess);
netif->flags |= NETIF_FLAG_LINK_UP;
}
@ -248,11 +234,10 @@ void ethernet_status_callback(struct netif *netif)
}
/**0
* \brief Manage the Ethernet packets, if any received process them.
* After processing any packets, manage the lwIP timers.
*
*
* \return Returns true if data has been processed.
*/
bool ethernet_read(void)
@ -275,6 +260,5 @@ bool ethernet_read(void)
*/
void ethernet_set_rx_callback(emac_dev_tx_cb_t callback)
{
ethernetif_set_rx_callback(callback);
}

View file

@ -54,18 +54,14 @@ extern "C" {
/**INDENT-ON**/
/// @endcond
bool status_link_up();//*****************************AB
/**
* \brief Initialize the ethernet interface.
*
*/
//void init_ethernet(void);
void init_ethernet(const u8_t macAddress[], const char *hostname);
void init_ethernet(void);
bool establish_ethernet_link(void);
void start_ethernet(const unsigned char ipAddress[], const unsigned char netMask[], const unsigned char gateWay[]);
void set_dhcp_hostname(const char *hostname);
struct netif* ethernet_get_configuration();

View file

@ -0,0 +1,337 @@
/**
* @file
* NetBIOS name service sample
*
*/
/*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
* This file is part of the lwIP TCP/IP stack.
*
*/
#include "lwipopts.h"
#if LWIP_UDP /* don't build if not configured for use in lwipopts.h */
#include "lwip/src/include/lwip/udp.h"
#include "lwip/src/include/lwip/netif.h"
#include <string.h>
/** This is an example implementation of a NetBIOS name server.
* It responds to name queries for a configurable name.
* Name resolving is not supported.
*
* Note that the device doesn't broadcast it's own name so can't
* detect duplicate names!
*/
/** NetBIOS name of LWIP device
* This must be uppercase until NETBIOS_STRCMP() is defined to a string
* comparision function that is case insensitive.
* If you want to use the netif's hostname, use this (with LWIP_NETIF_HOSTNAME):
* (ip_current_netif() != NULL ? ip_current_netif()->hostname != NULL ? ip_current_netif()->hostname : "" : "")
*/
#ifndef NETBIOS_LWIP_NAME
#define NETBIOS_LWIP_NAME (ip_current_netif() != NULL ? ip_current_netif()->hostname != NULL ? ip_current_netif()->hostname : "DUET" : "DUET")
#endif
/** Since there's no standard function for case-insensitive string comparision,
* we need another define here:
* define this to stricmp() for windows or strcasecmp() for linux.
* If not defined, comparision is case sensitive and NETBIOS_LWIP_NAME must be
* uppercase
*/
#ifndef NETBIOS_STRCMP
#define NETBIOS_STRCMP(str1, str2) stricmp(str1, str2)
#endif
/** default port number for "NetBIOS Name service */
#define NETBIOS_PORT 137
/** size of a NetBIOS name */
#define NETBIOS_NAME_LEN 16
/** The Time-To-Live for NetBIOS name responds (in seconds)
* Default is 300000 seconds (3 days, 11 hours, 20 minutes) */
#define NETBIOS_NAME_TTL 300000
/** NetBIOS header flags */
#define NETB_HFLAG_RESPONSE 0x8000U
#define NETB_HFLAG_OPCODE 0x7800U
#define NETB_HFLAG_OPCODE_NAME_QUERY 0x0000U
#define NETB_HFLAG_AUTHORATIVE 0x0400U
#define NETB_HFLAG_TRUNCATED 0x0200U
#define NETB_HFLAG_RECURS_DESIRED 0x0100U
#define NETB_HFLAG_RECURS_AVAILABLE 0x0080U
#define NETB_HFLAG_BROADCAST 0x0010U
#define NETB_HFLAG_REPLYCODE 0x0008U
#define NETB_HFLAG_REPLYCODE_NOERROR 0x0000U
/** NetBIOS name flags */
#define NETB_NFLAG_UNIQUE 0x8000U
#define NETB_NFLAG_NODETYPE 0x6000U
#define NETB_NFLAG_NODETYPE_HNODE 0x6000U
#define NETB_NFLAG_NODETYPE_MNODE 0x4000U
#define NETB_NFLAG_NODETYPE_PNODE 0x2000U
#define NETB_NFLAG_NODETYPE_BNODE 0x0000U
/** NetBIOS message header */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct netbios_hdr {
PACK_STRUCT_FIELD(u16_t trans_id);
PACK_STRUCT_FIELD(u16_t flags);
PACK_STRUCT_FIELD(u16_t questions);
PACK_STRUCT_FIELD(u16_t answerRRs);
PACK_STRUCT_FIELD(u16_t authorityRRs);
PACK_STRUCT_FIELD(u16_t additionalRRs);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
/** NetBIOS message name part */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct netbios_name_hdr {
PACK_STRUCT_FIELD(u8_t nametype);
PACK_STRUCT_FIELD(u8_t encname[(NETBIOS_NAME_LEN*2)+1]);
PACK_STRUCT_FIELD(u16_t type);
PACK_STRUCT_FIELD(u16_t cls);
PACK_STRUCT_FIELD(u32_t ttl);
PACK_STRUCT_FIELD(u16_t datalen);
PACK_STRUCT_FIELD(u16_t flags);
PACK_STRUCT_FIELD(ip_addr_p_t addr);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
/** NetBIOS message */
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/bpstruct.h"
#endif
PACK_STRUCT_BEGIN
struct netbios_resp
{
struct netbios_hdr resp_hdr;
struct netbios_name_hdr resp_name;
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
#ifdef PACK_STRUCT_USE_INCLUDES
# include "arch/epstruct.h"
#endif
/** NetBIOS decoding name */
static int
netbios_name_decoding( char *name_enc, char *name_dec, int name_dec_len)
{
char *pname;
char cname;
char cnbname;
int index = 0;
LWIP_UNUSED_ARG(name_dec_len);
/* Start decoding netbios name. */
pname = name_enc;
for (;;) {
/* Every two characters of the first level-encoded name
* turn into one character in the decoded name. */
cname = *pname;
if (cname == '\0')
break; /* no more characters */
if (cname == '.')
break; /* scope ID follows */
if (cname < 'A' || cname > 'Z') {
/* Not legal. */
return -1;
}
cname -= 'A';
cnbname = cname << 4;
pname++;
cname = *pname;
if (cname == '\0' || cname == '.') {
/* No more characters in the name - but we're in
* the middle of a pair. Not legal. */
return -1;
}
if (cname < 'A' || cname > 'Z') {
/* Not legal. */
return -1;
}
cname -= 'A';
cnbname |= cname;
pname++;
/* Do we have room to store the character? */
if (index < NETBIOS_NAME_LEN) {
/* Yes - store the character. */
name_dec[index++] = (cnbname!=' '?cnbname:'\0');
}
}
return 0;
}
#if 0 /* function currently unused */
/** NetBIOS encoding name */
static int
netbios_name_encoding(char *name_enc, char *name_dec, int name_dec_len)
{
char *pname;
char cname;
unsigned char ucname;
int index = 0;
/* Start encoding netbios name. */
pname = name_enc;
for (;;) {
/* Every two characters of the first level-encoded name
* turn into one character in the decoded name. */
cname = *pname;
if (cname == '\0')
break; /* no more characters */
if (cname == '.')
break; /* scope ID follows */
if ((cname < 'A' || cname > 'Z') && (cname < '0' || cname > '9')) {
/* Not legal. */
return -1;
}
/* Do we have room to store the character? */
if (index >= name_dec_len) {
return -1;
}
/* Yes - store the character. */
ucname = cname;
name_dec[index++] = ('A'+((ucname>>4) & 0x0F));
name_dec[index++] = ('A'+( ucname & 0x0F));
pname++;
}
/* Fill with "space" coding */
for (;index<name_dec_len-1;) {
name_dec[index++] = 'C';
name_dec[index++] = 'A';
}
/* Terminate string */
name_dec[index]='\0';
return 0;
}
#endif /* 0 */
/** NetBIOS Name service recv callback */
static void
netbios_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
{
LWIP_UNUSED_ARG(arg);
/* if packet is valid */
if (p != NULL) {
char netbios_name[NETBIOS_NAME_LEN+1];
struct netbios_hdr* netbios_hdr = (struct netbios_hdr*)p->payload;
struct netbios_name_hdr* netbios_name_hdr = (struct netbios_name_hdr*)(netbios_hdr+1);
/* we only answer if we got a default interface */
if (netif_default != NULL) {
/* @todo: do we need to check answerRRs/authorityRRs/additionalRRs? */
/* if the packet is a NetBIOS name query question */
if (((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_OPCODE)) == PP_NTOHS(NETB_HFLAG_OPCODE_NAME_QUERY)) &&
((netbios_hdr->flags & PP_NTOHS(NETB_HFLAG_RESPONSE)) == 0) &&
(netbios_hdr->questions == PP_NTOHS(1))) {
/* decode the NetBIOS name */
netbios_name_decoding( (char*)(netbios_name_hdr->encname), netbios_name, sizeof(netbios_name));
/* if the packet is for us */
if (NETBIOS_STRCMP(netbios_name, NETBIOS_LWIP_NAME) == 0) {
struct pbuf *q;
struct netbios_resp *resp;
q = pbuf_alloc(PBUF_TRANSPORT, sizeof(struct netbios_resp), PBUF_RAM);
if (q != NULL) {
resp = (struct netbios_resp*)q->payload;
/* prepare NetBIOS header response */
resp->resp_hdr.trans_id = netbios_hdr->trans_id;
resp->resp_hdr.flags = PP_HTONS(NETB_HFLAG_RESPONSE |
NETB_HFLAG_OPCODE_NAME_QUERY |
NETB_HFLAG_AUTHORATIVE |
NETB_HFLAG_RECURS_DESIRED);
resp->resp_hdr.questions = 0;
resp->resp_hdr.answerRRs = PP_HTONS(1);
resp->resp_hdr.authorityRRs = 0;
resp->resp_hdr.additionalRRs = 0;
/* prepare NetBIOS header datas */
MEMCPY( resp->resp_name.encname, netbios_name_hdr->encname, sizeof(netbios_name_hdr->encname));
resp->resp_name.nametype = netbios_name_hdr->nametype;
resp->resp_name.type = netbios_name_hdr->type;
resp->resp_name.cls = netbios_name_hdr->cls;
resp->resp_name.ttl = PP_HTONL(NETBIOS_NAME_TTL);
resp->resp_name.datalen = PP_HTONS(sizeof(resp->resp_name.flags)+sizeof(resp->resp_name.addr));
resp->resp_name.flags = PP_HTONS(NETB_NFLAG_NODETYPE_BNODE);
ip_addr_copy(resp->resp_name.addr, netif_default->ip_addr);
/* send the NetBIOS response */
udp_sendto(upcb, q, addr, port);
/* free the "reference" pbuf */
pbuf_free(q);
}
}
}
}
/* free the pbuf */
pbuf_free(p);
}
}
void netbios_init(void)
{
struct udp_pcb *pcb;
LWIP_ASSERT("NetBIOS name is too long!", strlen(NETBIOS_LWIP_NAME) < NETBIOS_NAME_LEN);
pcb = udp_new();
if (pcb != NULL) {
/* we have to be allowed to send broadcast packets! */
pcb->so_options |= SOF_BROADCAST;
udp_bind(pcb, IP_ADDR_ANY, NETBIOS_PORT);
udp_recv(pcb, netbios_recv, pcb);
}
}
#endif /* LWIP_UDP */

View file

@ -0,0 +1,6 @@
#ifndef __NETBIOS_H__
#define __NETBIOS_H__
void netbios_init(void);
#endif /* __NETBIOS_H__ */

View file

@ -76,7 +76,7 @@ typedef u8_t sys_mbox_t;
*/
#define SYS_MBOX_EMPTY SYS_ARCH_TIMEOUT
#include "lwip/err.h"
#include "err.h"
#include "arch/sys_arch.h"
/** Function prototype for thread functions */

View file

@ -53,12 +53,11 @@
bool ethernetif_phy_link_status(void); //*****************************AB
err_t ethernetif_init(struct netif *netif);
void ethernetif_set_params(const u8_t macAddress[], const char *hostname);
bool ethernetif_input(void *pv_parameters);
void ethernet_hardware_init(void);
bool ethernet_establish_link(void);
void RepRapNetworkSetMACAddress(const u8_t macAddress[]);
void ethernetif_set_rx_callback(emac_dev_tx_cb_t callback);
#endif /* ETHERNETIF_H_INCLUDED */

View file

@ -423,34 +423,18 @@ bool ethernetif_input(void * pvParameters)
struct netif *netif = (struct netif *)pvParameters;
struct pbuf *p;
#ifdef FREERTOS_USED
for( ;; ) {
do {
#endif
/* move received packet into a new pbuf */
p = low_level_input( netif );
if( p == NULL )
{
#ifdef FREERTOS_USED
/* No packet could be read. Wait a for an interrupt to tell us
there is more data available. */
vTaskDelay(100);
}
}while( p == NULL );
#else
return false;
}
#endif
if( ERR_OK != netif->input( p, netif ) )
{
pbuf_free(p);
p = NULL;
}
#ifdef FREERTOS_USED
/* move received packet into a new pbuf */
p = low_level_input( netif );
if( p == NULL )
{
return false;
}
#endif
if( ERR_OK != netif->input( p, netif ) )
{
pbuf_free(p);
p = NULL;
}
return true;
}
@ -475,7 +459,7 @@ err_t ethernetif_init(struct netif *netif)
#if LWIP_NETIF_HOSTNAME
/* Initialize interface hostname */
netif->hostname = "lwip";
// netif->hostname = "lwip"; // Unused! Duet sets hostname explicitly
#endif /* LWIP_NETIF_HOSTNAME */
/*
@ -517,17 +501,15 @@ err_t ethernetif_init(struct netif *netif)
return ERR_OK;
}
void RepRapNetworkSetMACAddress(const u8_t macAddress[])
{
size_t i;
for (i = 0; i < 8; ++i)
{
gs_uc_mac_address[i] = macAddress[i];
}
}
void ethernetif_set_rx_callback(emac_dev_tx_cb_t callback)
{
emac_dev_set_rx_callback(&gs_emac_dev, callback);
}
void ethernetif_set_mac_address(const u8_t macAddress[])
{
for (size_t i = 0; i < 8; ++i)
{
gs_uc_mac_address[i] = macAddress[i];
}
}

View file

@ -53,9 +53,6 @@
/* Include user defined options first */
#include "conf_eth.h"
#ifdef LWIP_DEBUG
#include "lwip/src/include/lwip/debug.h"
#endif
/* ---------- System options ---------- */
/* Specify NO_SYS because we are not using an RTOS */
@ -101,10 +98,10 @@ a lot of data that needs to be copied, this should be set high. */
#define UDP_TTL 255
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 1
#define MEMP_NUM_UDP_PCB 2
/* MEMP_NUM_TCP_PCB: the number of simultaneously active TCP connections. */
#define MEMP_NUM_TCP_PCB 12
#define MEMP_NUM_TCP_PCB 16
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 4
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP segments. */
@ -268,11 +265,4 @@ a lot of data that needs to be copied, this should be set high. */
// \note For a list of all possible lwIP configurations, check http://lwip.wikia.com/wiki/Lwipopts.h
/** EMAC PHY address */
#define BOARD_EMAC_PHY_ADDR 2
/*! EMAC RMII mode */
#define BOARD_EMAC_MODE_RMII 1
/**/
#endif /* __LWIPOPTS_H__ */

334
Move.cpp
View file

@ -7,242 +7,6 @@
#include "RepRapFirmware.h"
void DeltaParameters::Init()
{
deltaMode = false;
diagonal = 0.0;
radius = 0.0;
printRadius = defaultPrintRadius;
homedHeight = defaultDeltaHomedHeight;
isEquilateral = true;
for (size_t axis = 0; axis < AXES; ++axis)
{
endstopAdjustments[axis] = 0.0;
towerX[axis] = towerY[axis] = 0.0;
}
}
void DeltaParameters::SetRadius(float r)
{
radius = r;
isEquilateral = true;
const float cos30 = sqrtf(3.0)/2.0;
const float sin30 = 0.5;
towerX[A_AXIS] = -(r * cos30);
towerX[B_AXIS] = r * cos30;
towerX[C_AXIS] = 0.0;
towerY[A_AXIS] = towerY[B_AXIS] = -(r * sin30);
towerY[C_AXIS] = r;
Recalc();
}
void DeltaParameters::Recalc()
{
deltaMode = (radius > 0.0 && diagonal > radius);
if (deltaMode)
{
Xbc = towerX[C_AXIS] - towerX[B_AXIS];
Xca = towerX[A_AXIS] - towerX[C_AXIS];
Xab = towerX[B_AXIS] - towerX[A_AXIS];
Ybc = towerY[C_AXIS] - towerY[B_AXIS];
Yca = towerY[A_AXIS] - towerY[C_AXIS];
Yab = towerY[B_AXIS] - towerY[A_AXIS];
coreFa = fsquare(towerX[A_AXIS]) + fsquare(towerY[A_AXIS]);
coreFb = fsquare(towerX[B_AXIS]) + fsquare(towerY[B_AXIS]);
coreFc = fsquare(towerX[C_AXIS]) + fsquare(towerY[C_AXIS]);
Q = 2 * (Xca * Yab - Xab * Yca);
Q2 = fsquare(Q);
D2 = fsquare(diagonal);
// Calculate the base carriage height when the printer is homed.
const float tempHeight = diagonal; // any sensible height will do here, probably even zero
float machinePos[AXES];
InverseTransform(tempHeight + endstopAdjustments[X_AXIS], tempHeight + endstopAdjustments[Y_AXIS], tempHeight + endstopAdjustments[X_AXIS],
machinePos);
homedCarriageHeight = homedHeight + tempHeight - machinePos[Z_AXIS];
}
}
// Make the average of the endstop adjustments zero, without changing the individual homed carriage heights
void DeltaParameters::NormaliseEndstopAdjustments()
{
const float eav = (endstopAdjustments[A_AXIS] + endstopAdjustments[B_AXIS] + endstopAdjustments[C_AXIS])/3.0;
endstopAdjustments[A_AXIS] -= eav;
endstopAdjustments[B_AXIS] -= eav;
endstopAdjustments[C_AXIS] -= eav;
homedHeight += eav;
homedCarriageHeight += eav; // no need for a full recalc, this is sufficient
}
// Calculate the motor position for a single tower from a Cartesian coordinate
float DeltaParameters::Transform(const float machinePos[AXES], size_t axis) const
{
return machinePos[Z_AXIS]
+ sqrt(D2 - fsquare(machinePos[X_AXIS] - towerX[axis]) - fsquare(machinePos[Y_AXIS] - towerY[axis]));
}
void DeltaParameters::InverseTransform(float Ha, float Hb, float Hc, float machinePos[AXES]) const
{
const float Fa = coreFa + fsquare(Ha);
const float Fb = coreFb + fsquare(Hb);
const float Fc = coreFc + fsquare(Hc);
// debugPrintf("Ha=%f Hb=%f Hc=%f Fa=%f Fb=%f Fc=%f Xbc=%f Xca=%f Xab=%f Ybc=%f Yca=%f Yab=%f\n",
// Ha, Hb, Hc, Fa, Fb, Fc, Xbc, Xca, Xab, Ybc, Yca, Yab);
// Setup PQRSU such that x = -(S - uz)/P, y = (P - Rz)/Q
const float P = (Xbc * Fa) + (Xca * Fb) + (Xab * Fc);
const float S = (Ybc * Fa) + (Yca * Fb) + (Yab * Fc);
const float R = 2 * ((Xbc * Ha) + (Xca * Hb) + (Xab * Hc));
const float U = 2 * ((Ybc * Ha) + (Yca * Hb) + (Yab * Hc));
// debugPrintf("P= %f R=%f S=%f U=%f Q=%f\n", P, R, S, U, Q);
const float R2 = fsquare(R), U2 = fsquare(U);
float A = U2 + R2 + Q2;
float minusHalfB = S * U + P * R + Ha * Q2 + towerX[A_AXIS] * U * Q - towerY[A_AXIS] * R * Q;
float C = fsquare(S + towerX[A_AXIS] * Q) + fsquare(P - towerY[A_AXIS] * Q) + (fsquare(Ha) - D2) * Q2;
// debugPrintf("A=%f minusHalfB=%f C=%f\n", A, minusHalfB, C);
float z = (minusHalfB - sqrtf(fsquare(minusHalfB) - A * C)) / A;
machinePos[X_AXIS] = (U * z - S) / Q;
machinePos[Y_AXIS] = (P - R * z) / Q;
machinePos[Z_AXIS] = z;
}
// Compute the derivative of height with respect to a parameter at the specified motor endpoints.
// 'deriv' indicates the parameter as follows:
// 0, 1, 2 = X, Y, Z tower endstop adjustments
// 3, 4 = X, Y tower X position
// 5 = Z tower Y position
// 6 = diagonal rod length
// 7 = delta radius (only if isEquilateral is true)
float DeltaParameters::ComputeDerivative(unsigned int deriv, float ha, float hb, float hc)
{
const float perturb = 0.2; // perturbation amount in mm
DeltaParameters hiParams(*this), loParams(*this);
switch(deriv)
{
case 0:
case 1:
case 2:
break;
case 3:
case 4:
hiParams.towerX[deriv - 3] += perturb;
loParams.towerX[deriv - 3] -= perturb;
break;
case 5:
{
const float yAdj = perturb * (1.0/3.0);
hiParams.towerY[A_AXIS] -= yAdj;
hiParams.towerY[B_AXIS] -= yAdj;
hiParams.towerY[C_AXIS] += (perturb - yAdj);
loParams.towerY[A_AXIS] += yAdj;
loParams.towerY[B_AXIS] += yAdj;
loParams.towerY[C_AXIS] -= (perturb - yAdj);
}
break;
case 6:
hiParams.diagonal += perturb;
loParams.diagonal -= perturb;
break;
case 7:
hiParams.SetRadius(radius + perturb);
loParams.SetRadius(radius - perturb);
break;
}
hiParams.Recalc();
loParams.Recalc();
float newPos[AXES];
hiParams.InverseTransform((deriv == 0) ? ha + perturb : ha, (deriv == 1) ? hb + perturb : hb, (deriv == 2) ? hc + perturb : hc, newPos);
float zHi = newPos[Z_AXIS];
loParams.InverseTransform((deriv == 0) ? ha - perturb : ha, (deriv == 1) ? hb - perturb : hb, (deriv == 2) ? hc - perturb : hc, newPos);
float zLo = newPos[Z_AXIS];
return (zHi - zLo)/(2 * perturb);
}
// Perform 3, 4, 6 or 7-factor adjustment.
// The input vector contains the following parameters in this order:
// X, Y and Z endstop adjustments
// If we are doing 4-factor adjustment, the next argument is the delta radius. Otherwise:
// X tower X position adjustment
// Y tower X position adjustment
// Z tower Y position adjustment
// Diagonal rod length adjustment
void DeltaParameters::Adjust(size_t numFactors, const float v[])
{
const float oldCarriageHeightA = GetHomedCarriageHeight(A_AXIS); // save for later
// Update endstop adjustments
endstopAdjustments[A_AXIS] += v[0];
endstopAdjustments[B_AXIS] += v[1];
endstopAdjustments[C_AXIS] += v[2];
NormaliseEndstopAdjustments();
if (numFactors == 4)
{
// 4-factor adjustment, so update delta radius
SetRadius(radius + v[3]); // this sets isEquilateral true, recalculates tower positions, then calls Recalc()
}
else if (numFactors > 3)
{
// 6- or 7-factor adjustment
towerX[A_AXIS] += v[3];
towerX[B_AXIS] += v[4];
const float yAdj = v[5] * (1.0/3.0);
towerY[A_AXIS] -= yAdj;
towerY[B_AXIS] -= yAdj;
towerY[C_AXIS] += (v[5] - yAdj);
isEquilateral = false;
if (numFactors == 7)
{
diagonal += v[6];
}
Recalc();
}
// Adjusting the diagonal and the tower positions affects the homed carriage height.
// We need to adjust homedHeight to allow for this, to get the change that was requested in the endstop corrections.
const float heightError = GetHomedCarriageHeight(A_AXIS) - oldCarriageHeightA - v[0];
homedHeight -= heightError;
homedCarriageHeight -= heightError;
}
void DeltaParameters::PrintParameters(StringRef& reply, bool full)
{
reply.printf("Endstops X%.2f Y%.2f Z%.2f, height %.2f, diagonal %.2f, ",
endstopAdjustments[A_AXIS], endstopAdjustments[B_AXIS], endstopAdjustments[C_AXIS], homedHeight, diagonal);
if (isEquilateral && !full)
{
reply.catf("radius %.2f\n", radius);
}
else
{
reply.catf("towers (%.2f,%.2f) (%.2f,%.2f) (%.2f,%.2f)\n",
towerX[A_AXIS], towerY[A_AXIS], towerX[B_AXIS], towerY[B_AXIS], towerX[C_AXIS], towerY[C_AXIS]);
}
}
Move::Move(Platform* p, GCodes* g) : currentDda(NULL)
{
active = false;
@ -265,6 +29,7 @@ void Move::Init()
// Reset Cartesian mode
deltaParams.Init();
coreXYMode = 0;
deltaProbing = false;
// Empty the ring
ddaRingGetPointer = ddaRingAddPointer;
@ -437,7 +202,7 @@ void Move::Spin()
ddaRingGetPointer = ddaRingGetPointer->GetNext();
}
}
else
else if (!deltaProbing)
{
// See whether we need to kick off a move
DDA *cdda = currentDda; // currentDda is volatile, so copy it
@ -1242,13 +1007,59 @@ float Move::SecondDegreeTransformZ(float x, float y) const
return (1.0 - x)*(1.0 - y)*zBedProbePoints[0] + x*(1.0 - y)*zBedProbePoints[3] + (1.0 - x)*y*zBedProbePoints[1] + x*y*zBedProbePoints[2];
}
static void ShortDelay()
{
for (unsigned int i = 0; i < 10; ++i)
{
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
}
}
// This is the function that's called by the timer interrupt to step the motors.
void Move::Interrupt()
{
bool again = true;
while (again && currentDda != nullptr)
if (deltaProbing)
{
again = currentDda->Step();
bool again = true;
while (again)
{
if (reprap.GetPlatform()->GetZProbeResult() == EndStopHit::lowHit)
{
deltaProbe.Trigger();
}
bool dir = deltaProbe.GetDirection();
Platform *platform = reprap.GetPlatform();
platform->SetDirection(X_AXIS, dir);
platform->SetDirection(Y_AXIS, dir);
platform->SetDirection(Z_AXIS, dir);
ShortDelay();
platform->StepHigh(X_AXIS);
platform->StepHigh(Y_AXIS);
platform->StepHigh(Z_AXIS);
ShortDelay();
platform->StepLow(X_AXIS);
platform->StepLow(Y_AXIS);
platform->StepLow(Z_AXIS);
uint32_t tim = deltaProbe.CalcNextStepTime();
again = (tim != 0xFFFFFFFF && platform->ScheduleInterrupt(tim + deltaProbingStartTime));
}
}
else
{
bool again = true;
while (again && currentDda != nullptr)
{
again = currentDda->Step();
}
}
}
@ -1530,6 +1341,49 @@ const char* Move::GetGeometryString() const
: "cartesian";
}
// Do a delta probe returning -1 if still probing, 0 if failed, 1 if success
int Move::DoDeltaProbe(float frequency, float amplitude, float rate, float distance)
{
if (deltaProbing)
{
if (deltaProbe.Finished())
{
deltaProbing = false;
return (deltaProbe.Overran()) ? 0 : 1;
}
}
else
{
if (currentDda != nullptr || !DDARingEmpty())
{
return 0;
}
if (!deltaProbe.Init(frequency, amplitude, rate, distance))
{
return 0;
}
const uint32_t firstInterruptTime = deltaProbe.Start();
if (firstInterruptTime != 0xFFFFFFFF)
{
Platform *platform = reprap.GetPlatform();
platform->EnableDrive(X_AXIS);
platform->EnableDrive(Y_AXIS);
platform->EnableDrive(Z_AXIS);
deltaProbing = true;
iState = IdleState::busy;
const irqflags_t flags = cpu_irq_save();
deltaProbingStartTime = platform->GetInterruptClocks();
if (platform->ScheduleInterrupt(firstInterruptTime + deltaProbingStartTime))
{
Interrupt();
}
cpu_irq_restore(flags);
}
}
return -1;
}
/*static*/ void Move::PrintMatrix(const char* s, const MathMatrix<float>& m, size_t maxRows, size_t maxCols)
{
debugPrintf("%s\n", s);

63
Move.h
View file

@ -10,6 +10,8 @@
#include "DDA.h"
#include "Matrix.h"
#include "DeltaParameters.h"
#include "DeltaProbe.h"
const unsigned int DdaRingLength = 20;
@ -23,62 +25,6 @@ enum PointCoordinateSet
probeError = 16
};
// Class to hold the parameter for a delta machine.
// Some of the values that are currently calculated on demand could be pre-calculated in Recalc() and stored instead.
class DeltaParameters
{
public:
DeltaParameters() { Init(); }
bool IsDeltaMode() const { return deltaMode; }
bool IsEquilateral() const { return isEquilateral; }
float GetDiagonal() const { return diagonal; }
float GetRadius() const { return radius; }
float GetPrintRadius() const { return printRadius; }
float GetTowerX(size_t axis) const { return towerX[axis]; }
float GetTowerY(size_t axis) const { return towerY[axis]; }
float GetEndstopAdjustment(size_t axis) const { return endstopAdjustments[axis]; }
float GetHomedCarriageHeight(size_t axis) const { return homedCarriageHeight + endstopAdjustments[axis]; }
float GetPrintRadiusSquared() const { return printRadiusSquared; }
void Init();
void SetDiagonal(float d) { diagonal = d; Recalc(); }
void SetRadius(float r);
void SetEndstopAdjustment(size_t axis, float x) { endstopAdjustments[axis] = x; }
void SetPrintRadius(float r) { printRadius = r; printRadiusSquared = r * r; }
float GetHomedHeight() const { return homedHeight; }
void SetHomedHeight(float h) { homedHeight = h; Recalc(); }
float Transform(const float machinePos[AXES], size_t axis) const; // Calculate the motor position for a single tower from a Cartesian coordinate
void InverseTransform(float Ha, float Hb, float Hc, float machinePos[AXES]) const; // Calculate the Cartesian position from the motor positions
float ComputeDerivative(unsigned int deriv, float ha, float hb, float hc); // Compute the derivative of height with respect to a parameter at a set of motor endpoints
void Adjust(size_t numFactors, const float v[]); // Perform 4-, 6- or 7-factor adjustment
void PrintParameters(StringRef& reply, bool full);
private:
void Recalc();
void NormaliseEndstopAdjustments(); // Make the average of the endstop adjustments zero
// Core parameters
float diagonal; // The diagonal rod length, all 3 are assumed to be the same length
float radius; // The nominal delta radius, before any fine tuning of tower positions
float towerX[AXES]; // The X coordinate of each tower
float towerY[AXES]; // The Y coordinate of each tower
float endstopAdjustments[AXES]; // How much above or below the ideal position each endstop is
float printRadius;
float homedHeight;
// Derived values
bool deltaMode; // True if this is a delta printer
bool isEquilateral; // True if the towers are at the corners of an equilateral triangle
float printRadiusSquared;
float homedCarriageHeight;
float Xbc, Xca, Xab, Ybc, Yca, Yab;
float coreFa, coreFb, coreFc;
float Q, Q2, D2;
};
/**
* This is the master movement class. It controls all movement in the machine.
*/
@ -143,6 +89,8 @@ public:
FilePosition PausePrint(float positions[DRIVES+1]); // Pause the print as soon as we can
bool NoLiveMovement() const; // Is a move running, or are there any queued?
int DoDeltaProbe(float frequency, float amplitude, float rate, float distance);
static int32_t MotorEndPointToMachine(size_t drive, float coord); // Convert a single motor position to number of steps
static float MotorEndpointToPosition(int32_t endpoint, size_t drive); // Convert number of motor steps to motor position
@ -202,6 +150,9 @@ private:
IdleState iState; // whether the idle timer is active
DeltaParameters deltaParams; // Information about the delta parameters of this machine
DeltaProbe deltaProbe; // Delta probing state
uint32_t deltaProbingStartTime;
bool deltaProbing;
int coreXYMode; // 0 = Cartesian, 1 = CoreXY, 2 = CoreXZ, 3 = CoreYZ
};

View file

@ -49,8 +49,7 @@ extern "C"
{
#include "lwipopts.h"
#include "lwip/src/include/lwip/tcp.h"
void RepRapNetworkSetMACAddress(const u8_t macAddress[]);
#include "contrib/apps/netbios/netbios.h"
}
static tcp_pcb *http_pcb = NULL;
@ -326,23 +325,24 @@ Network::Network(Platform* p)
freeTransactions(NULL), readyTransactions(NULL), writingTransactions(NULL),
dataCs(NULL), ftpCs(NULL), telnetCs(NULL), freeSendBuffers(NULL), freeConnections(NULL)
{
for (unsigned int i = 0; i < networkTransactionCount; i++)
for (size_t i = 0; i < networkTransactionCount; i++)
{
freeTransactions = new NetworkTransaction(freeTransactions);
}
for (unsigned int i = 0; i < tcpOutputBufferCount; i++)
for (size_t i = 0; i < tcpOutputBufferCount; i++)
{
freeSendBuffers = new SendBuffer(freeSendBuffers);
}
for (unsigned int i = 0; i < numConnections; i++)
for (size_t i = 0; i < numConnections; i++)
{
ConnectionState *cs = new ConnectionState;
cs->next = freeConnections;
freeConnections = cs;
}
strcpy(hostname, HOSTNAME);
ethPinsInit();
}
@ -369,8 +369,7 @@ void Network::Init()
platform->Message(HOST_MESSAGE, "Attempting to start the network when it is disabled.\n");
return;
}
RepRapNetworkSetMACAddress(platform->MACAddress());
init_ethernet();
init_ethernet(platform->MACAddress(), hostname);
longWait = platform->Time();
state = NetworkInitializing;
}
@ -426,12 +425,13 @@ void Network::Spin()
}
else if (state == NetworkInitializing && establish_ethernet_link())
{
set_dhcp_hostname(reprap.GetName());
start_ethernet(platform->IPAddress(), platform->NetMask(), platform->GateWay());
ethernet_set_rx_callback(&emac_read_packet);
httpd_init();
ftpd_init();
telnetd_init();
ethernet_set_rx_callback(&emac_read_packet);
netbios_init();
state = NetworkActive;
}
@ -1039,6 +1039,34 @@ bool Network::AcquireTransaction(ConnectionState *cs)
return true;
}
// Set the DHCP hostname. Removes all whitespaces and converts the name to lower-case.
void Network::SetHostname(const char *name)
{
size_t i = 0;
while (*name && i < ARRAY_UPB(hostname))
{
char c = *name++;
if (c >= 'A' && c <= 'Z')
{
c += 'a' - 'A';
}
if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c == '-') || (c == '_'))
{
hostname[i++] = c;
}
}
if (i)
{
hostname[i] = 0;
}
else
{
strcpy(hostname, HOSTNAME);
}
}
// Initialise a ConnectionState for a new connection
void ConnectionState::Init(tcp_pcb *p)
{

View file

@ -38,6 +38,7 @@ const float writeTimeout = 4.0; // seconds to wait for data we have writ
#define IP_ADDRESS {192, 168, 1, 10} // Need some sort of default...
#define NET_MASK {255, 255, 255, 0}
#define GATE_WAY {192, 168, 1, 1}
#define HOSTNAME "duet"
/****************************************************************************************************/
@ -183,6 +184,8 @@ public:
void SetHttpPort(uint16_t port);
uint16_t GetHttpPort() const;
void SetHostname(const char *name);
private:
Platform* platform;
@ -202,6 +205,7 @@ private:
enum { NetworkInactive, NetworkInitializing, NetworkActive } state;
bool isEnabled;
bool volatile readingData;
char hostname[16]; // limit DHCP hostname to 15 characters + terminating 0
ConnectionState *dataCs;
ConnectionState *ftpCs;

View file

@ -240,7 +240,7 @@ void Platform::Init()
SetElasticComp(drive, 0.0);
if (drive <= AXES)
{
endStopType[drive] = lowEndStop; // assume all endstops are low endstops
endStopType[drive] = EndStopType::lowEndStop; // assume all endstops are low endstops
endStopLogicLevel[drive] = true;
}
}
@ -337,6 +337,9 @@ void Platform::InitZProbe()
pinModeNonDue(endStopPins[E0_AXIS], INPUT_PULLUP);
break;
case 5:
break; //TODO
default:
break;
}
@ -375,6 +378,8 @@ int Platform::ZProbe() const
// Because of noise, it is possible to get a negative reading, so allow for this.
return (int) (((int32_t) zProbeOnFilter.GetSum() - (int32_t) zProbeOffFilter.GetSum())
/ (int)(4 * numZProbeReadingsAveraged));
case 5:
return (int) ((zProbeOnFilter.GetSum() + zProbeOffFilter.GetSum()) / (8 * numZProbeReadingsAveraged)); //TODO this is temporary
default:
break;
@ -436,6 +441,7 @@ float Platform::ZProbeStopHeight() const
case 2:
return nvData.irZProbeParameters.GetStopHeight(GetTemperature(0));
case 3:
case 5:
return nvData.alternateZProbeParameters.GetStopHeight(GetTemperature(0));
default:
return 0;
@ -450,6 +456,7 @@ float Platform::GetZProbeDiveHeight() const
case 2:
return nvData.irZProbeParameters.diveHeight;
case 3:
case 5:
return nvData.alternateZProbeParameters.diveHeight;
case 4:
return nvData.switchZProbeParameters.diveHeight;
@ -467,6 +474,7 @@ void Platform::SetZProbeDiveHeight(float h)
nvData.irZProbeParameters.diveHeight = h;
break;
case 3:
case 5:
nvData.alternateZProbeParameters.diveHeight = h;
break;
case 4:
@ -479,7 +487,7 @@ void Platform::SetZProbeDiveHeight(float h)
void Platform::SetZProbeType(int pt)
{
int newZProbeType = (pt >= 0 && pt <= 4) ? pt : 0;
int newZProbeType = (pt >= 0 && pt <= 5) ? pt : 0;
if (newZProbeType != nvData.zProbeType)
{
nvData.zProbeType = newZProbeType;
@ -503,6 +511,7 @@ const ZProbeParameters& Platform::GetZProbeParameters() const
case 2:
return nvData.irZProbeParameters;
case 3:
case 5:
return nvData.alternateZProbeParameters;
}
}
@ -534,6 +543,7 @@ bool Platform::SetZProbeParameters(const struct ZProbeParameters& params)
}
return true;
case 3:
case 5:
if (nvData.alternateZProbeParameters != params)
{
nvData.alternateZProbeParameters = params;
@ -730,41 +740,49 @@ void Platform::Spin()
void Platform::SoftwareReset(uint16_t reason)
{
if (reason != SoftwareResetReason::user)
if (reason == SoftwareResetReason::erase)
{
if (line->inWrite)
{
reason |= SoftwareResetReason::inUsbOutput; // if we are resetting because we are stuck in a Spin function, record whether we are trying to send to USB
}
if (reprap.GetNetwork()->InLwip())
{
reason |= SoftwareResetReason::inLwipSpin;
}
if (aux->inWrite)
{
reason |= SoftwareResetReason::inAuxOutput; // if we are resetting because we are stuck in a Spin function, record whether we are trying to send to aux
}
}
reason |= reprap.GetSpinningModule();
// Record the reason for the software reset
SoftwareResetData temp;
temp.magic = SoftwareResetData::magicValue;
temp.resetReason = reason;
GetStackUsage(NULL, NULL, &temp.neverUsedRam);
if (reason != SoftwareResetReason::user)
{
strncpy(temp.lastMessage, messageString.Pointer(), sizeof(temp.lastMessage) - 1);
temp.lastMessage[sizeof(temp.lastMessage) - 1] = 0;
}
cpu_irq_disable();
flash_unlock(0x00080000, 0x000FFFFF, nullptr, nullptr);
flash_clear_gpnvm(1); // tell the system to boot from flash next time
}
else
{
temp.lastMessage[0] = 0;
if (reason != SoftwareResetReason::user)
{
if (line->inWrite)
{
reason |= SoftwareResetReason::inUsbOutput; // if we are resetting because we are stuck in a Spin function, record whether we are trying to send to USB
}
if (reprap.GetNetwork()->InLwip())
{
reason |= SoftwareResetReason::inLwipSpin;
}
if (aux->inWrite)
{
reason |= SoftwareResetReason::inAuxOutput; // if we are resetting because we are stuck in a Spin function, record whether we are trying to send to aux
}
}
reason |= reprap.GetSpinningModule();
// Record the reason for the software reset
SoftwareResetData temp;
temp.magic = SoftwareResetData::magicValue;
temp.resetReason = reason;
GetStackUsage(NULL, NULL, &temp.neverUsedRam);
if (reason != SoftwareResetReason::user)
{
strncpy(temp.lastMessage, messageString.Pointer(), sizeof(temp.lastMessage) - 1);
temp.lastMessage[sizeof(temp.lastMessage) - 1] = 0;
}
else
{
temp.lastMessage[0] = 0;
}
// Save diagnostics data to Flash and reset the software
DueFlashStorage::write(SoftwareResetData::nvAddress, &temp, sizeof(SoftwareResetData));
}
// Save diagnostics data to Flash and reset the software
DueFlashStorage::write(SoftwareResetData::nvAddress, &temp, sizeof(SoftwareResetData));
rstc_start_software_reset(RSTC);
for(;;) {}
}
@ -1190,14 +1208,14 @@ EndStopHit Platform::Stopped(size_t drive) const
return GetZProbeResult(); // using the Z probe as am endstop for this axis, so just get its result
}
if (endStopPins[drive] >= 0 && endStopType[drive] != noEndStop)
if (endStopPins[drive] >= 0 && endStopType[drive] != EndStopType::noEndStop)
{
if (digitalReadNonDue(endStopPins[drive]) == ((endStopLogicLevel[drive]) ? 1 : 0))
{
return (endStopType[drive] == highEndStop) ? highHit : lowHit;
return (endStopType[drive] == EndStopType::highEndStop) ? EndStopHit::highHit : EndStopHit::lowHit;
}
}
return noStop;
return EndStopHit::noStop;
}
// Return the Z probe result. We assume that if the Z probe is used as an endstop, it is used as the low stop.
@ -1208,9 +1226,9 @@ EndStopHit Platform::GetZProbeResult() const
(nvData.zProbeType == 4) ? nvData.switchZProbeParameters.adcValue
: (nvData.zProbeType == 3) ? nvData.alternateZProbeParameters.adcValue
: nvData.irZProbeParameters.adcValue;
return (zProbeVal >= zProbeADValue) ? lowHit
: (zProbeVal * 10 >= zProbeADValue * 9) ? lowNear // if we are at/above 90% of the target value
: noStop;
return (zProbeVal >= zProbeADValue) ? EndStopHit::lowHit
: (zProbeVal * 10 >= zProbeADValue * 9) ? EndStopHit::lowNear // if we are at/above 90% of the target value
: EndStopHit::noStop;
}
// This is called from the step ISR as well as other places, so keep it fast, especially in the case where the motor is already enabled
@ -2094,18 +2112,18 @@ float FileStore::FractionRead() const
return (float)GetPosition() / (float)len;
}
int8_t FileStore::Status()
uint8_t FileStore::Status()
{
if (!inUse)
return nothing;
return (uint8_t)IOStatus::nothing;
if (lastBufferEntry == FILE_BUF_LEN)
return byteAvailable;
return (uint8_t)IOStatus::byteAvailable;
if (bufferPointer < lastBufferEntry)
return byteAvailable;
return (uint8_t)IOStatus::byteAvailable;
return nothing;
return (uint8_t)IOStatus::nothing;
}
bool FileStore::ReadBuffer()
@ -2282,11 +2300,9 @@ Line::Line(Stream& p_iface) : iface(p_iface)
{
}
int8_t Line::Status() const
uint8_t Line::Status() const
{
// if(alternateInput != NULL)
// return alternateInput->Status();
return inputNumChars == 0 ? nothing : byteAvailable;
return inputNumChars == 0 ? (uint8_t)IOStatus::nothing : (uint8_t)IOStatus::byteAvailable;
}
// This is only ever called on initialisation, so we

View file

@ -218,7 +218,7 @@ const size_t messageStringLength = 256; // max length of a message chunk sent
/****************************************************************************************************/
enum EndStopHit
enum class EndStopHit
{
noStop = 0, // no endstop hit
lowHit = 1, // low switch hit, or Z-probe in use and above threshold
@ -227,7 +227,7 @@ enum EndStopHit
};
// The values of the following enumeration must tally with the definitions for the M574 command
enum EndStopType
enum class EndStopType
{
noEndStop = 0,
lowEndStop = 1,
@ -236,7 +236,7 @@ enum EndStopType
/***************************************************************************************************/
// Input and output - these are ORed into an int8_t
// Input and output - these are ORed into a uint8_t
// By the Status() functions of the IO classes.
enum IOStatus
@ -255,6 +255,7 @@ namespace SoftwareResetReason
enum
{
user = 0, // M999 command
erase = 55, // special M999 command to erase firmware and reset
inAuxOutput = 0x0800, // this bit is or'ed in if we were in aux output at the time
stuckInSpin = 0x1000, // we got stuck in a Spin() function for too long
inLwipSpin = 0x2000, // we got stuck in a call to LWIP for too long
@ -279,7 +280,7 @@ class Line
{
public:
int8_t Status() const; // Returns OR of IOStatus
uint8_t Status() const; // Returns OR of IOStatus
int Read(char& b);
void Write(char b, bool block = false);
void Write(const char* s, bool block = false);
@ -367,7 +368,7 @@ class FileStore
{
public:
int8_t Status(); // Returns OR of IOStatus
uint8_t Status(); // Returns OR of IOStatus
bool Read(char& b); // Read 1 byte
int Read(char* buf, unsigned int nBytes); // Read a block of nBytes length
bool Write(char b); // Write 1 byte
@ -425,6 +426,7 @@ struct ZProbeParameters
float calibTemperature; // the temperature at which we did the calibration
float temperatureCoefficient; // the variation of height with bed temperature
float diveHeight; // the dive height we use when probing
float param1, param2; // extra parameters used by some types of probe e.g. Delta probe
void Init(float h)
{
@ -434,6 +436,7 @@ struct ZProbeParameters
calibTemperature = 20.0;
temperatureCoefficient = 0.0; // no default temperature correction
diveHeight = DefaultZDive;
param1 = param2 = 0.0;
}
float GetStopHeight(float temperature) const
@ -449,7 +452,9 @@ struct ZProbeParameters
&& yOffset == other.yOffset
&& calibTemperature == other.calibTemperature
&& temperatureCoefficient == other.temperatureCoefficient
&& diveHeight == other.diveHeight;
&& diveHeight == other.diveHeight
&& param1 == other.param1
&& param2 == other.param2;
}
bool operator!=(const ZProbeParameters& other) const
@ -1303,7 +1308,7 @@ inline void Platform::GetEndStopConfiguration(size_t axis, EndStopType& esType,
// This is called by the tick ISR to get the raw Z probe reading to feed to the filter
inline uint16_t Platform::GetRawZProbeReading() const
{
if (nvData.zProbeType == 4)
if (nvData.zProbeType >= 4)
{
bool b = (bool)digitalRead(endStopPins[E0_AXIS]);
if (!endStopLogicLevel[AXES])

View file

@ -26,6 +26,11 @@ PrintMonitor::PrintMonitor(Platform *p, GCodes *gc) : platform(p), gCodes(gc), f
{
}
void PrintMonitor::Init()
{
longWait = platform->Time();
}
void PrintMonitor::Spin()
{
if (gCodes->IsPausing() || gCodes->IsPaused() || gCodes->IsResuming())
@ -135,7 +140,7 @@ void PrintMonitor::Spin()
}
else
{
for(unsigned int i=1; i<MAX_LAYER_SAMPLES; i++)
for(size_t i=1; i<MAX_LAYER_SAMPLES; i++)
{
layerDurations[i - 1] = layerDurations[i];
filamentUsagePerLayer[i - 1] = filamentUsagePerLayer[i];
@ -153,7 +158,7 @@ void PrintMonitor::Spin()
if (numLayerSamples)
{
avgLayerTime = 0.0;
for(unsigned int layer=0; layer<numLayerSamples; layer++)
for(size_t layer=0; layer<numLayerSamples; layer++)
{
avgLayerTime += layerDurations[layer];
if (layer)
@ -183,33 +188,29 @@ void PrintMonitor::Spin()
}
}
}
else if (printStartTime > 0.0 && reprap.GetMove()->NoLiveMovement())
{
currentLayer = numLayerSamples = 0;
firstLayerDuration = firstLayerHeight = firstLayerFilament = firstLayerProgress = 0.0;
layerEstimatedTimeLeft = printStartTime = warmUpDuration = 0.0;
lastLayerTime = lastLayerFilament = 0.0;
}
platform->ClassReport(longWait);
}
void PrintMonitor::Init()
{
longWait = platform->Time();
}
void PrintMonitor::StartingFilePrint(const char* filename)
void PrintMonitor::StartingPrint(const char* filename)
{
fileInfoDetected = GetFileInfo(platform->GetGCodeDir(), filename, currentFileInfo);
strncpy(fileBeingPrinted, filename, ARRAY_SIZE(fileBeingPrinted));
fileBeingPrinted[ARRAY_UPB(fileBeingPrinted)] = 0;
}
void PrintMonitor::StartedFilePrint()
void PrintMonitor::StartedPrint()
{
printStartTime = platform->Time();
}
void PrintMonitor::StoppedPrint()
{
currentLayer = numLayerSamples = 0;
firstLayerDuration = firstLayerHeight = firstLayerFilament = firstLayerProgress = 0.0;
layerEstimatedTimeLeft = printStartTime = warmUpDuration = 0.0;
lastLayerTime = lastLayerFilament = 0.0;
}
bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, GcodeFileInfo& info) const
{
if (reprap.GetPlatform()->GetMassStorage()->PathExists(directory, fileName))
@ -225,11 +226,11 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, Gcod
info.fileSize = f->Length();
info.objectHeight = 0.0;
info.layerHeight = 0.0;
info.numFilaments = DRIVES - AXES;
info.numFilaments = 0;
info.generatedBy[0] = 0;
for (size_t i = 0; i < DRIVES - AXES; ++i)
for(size_t extr=0; extr<DRIVES - AXES; extr++)
{
info.filamentNeeded[i] = 0.0;
info.filamentNeeded[extr] = 0.0;
}
if (info.fileSize != 0 && (StringEndsWith(fileName, ".gcode") || StringEndsWith(fileName, ".g") || StringEndsWith(fileName, ".gco") || StringEndsWith(fileName, ".gc")))
@ -261,7 +262,7 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, Gcod
nFilaments = FindFilamentUsed(buf, sizeToRead, filaments, DRIVES - AXES);
if (nFilaments != 0 && nFilaments >= filamentsFound)
{
filamentsFound = min<unsigned int>(nFilaments, info.numFilaments);
filamentsFound = nFilaments;
for (unsigned int i = 0; i < filamentsFound; ++i)
{
info.filamentNeeded[i] = filaments[i];
@ -374,7 +375,7 @@ bool PrintMonitor::GetFileInfo(const char *directory, const char *fileName, Gcod
nFilaments = FindFilamentUsed(buf, sizeToScan, filaments, DRIVES - AXES);
if (nFilaments != 0 && nFilaments >= filamentsFound)
{
filamentsFound = min<unsigned int>(nFilaments, info.numFilaments);
filamentsFound = nFilaments;
for (unsigned int i = 0; i < filamentsFound; ++i)
{
info.filamentNeeded[i] = filaments[i];

View file

@ -44,8 +44,9 @@ class PrintMonitor
void Spin();
void Init();
void StartingFilePrint(const char *filename); // called to indicate a file will be printed (see M23)
void StartedFilePrint(); // called whenever a new live print starts (see M24)
void StartingPrint(const char *filename); // called to indicate a file will be printed (see M23)
void StartedPrint(); // called whenever a new live print starts (see M24)
void StoppedPrint(); // called whenever a file print has stopped
bool GetFileInfo(const char *directory, const char *fileName, GcodeFileInfo& info) const;
void GetFileInfoResponse(StringRef& response, const char* filename) const;

Binary file not shown.

View file

@ -1456,6 +1456,9 @@ void RepRap::SetName(const char* nm)
{
// Users sometimes put a tab character between the machine name and the comment, so allow for this
CopyParameterText(nm, myName, ARRAY_SIZE(myName));
// Set new DHCP hostname
network->SetHostname(myName);
}
// Given that we want to extrude/etract the specified extruder drives, check if they are allowed.