Started to add code to implement look-ahead.
This commit is contained in:
parent
438737f2f2
commit
0c77a2f5eb
6 changed files with 280 additions and 31 deletions
|
@ -48,7 +48,6 @@ Licence: GPL
|
||||||
#define CLIENT_CLOSE_DELAY 1000 // Microseconds to wait after serving a page
|
#define CLIENT_CLOSE_DELAY 1000 // Microseconds to wait after serving a page
|
||||||
|
|
||||||
#define INDEX_PAGE "reprap.htm"
|
#define INDEX_PAGE "reprap.htm"
|
||||||
#define PRINT_PAGE "print.php"
|
|
||||||
#define MESSAGE_FILE "messages.txt"
|
#define MESSAGE_FILE "messages.txt"
|
||||||
#define FOUR04_FILE "html404.htm"
|
#define FOUR04_FILE "html404.htm"
|
||||||
#define KO_START "rr_"
|
#define KO_START "rr_"
|
||||||
|
@ -62,4 +61,7 @@ Licence: GPL
|
||||||
|
|
||||||
#define RING_LENGTH 10
|
#define RING_LENGTH 10
|
||||||
|
|
||||||
|
#define LOOK_AHEAD_LENGTH 25
|
||||||
|
#define LOOK_AHEAD_FLUSH 5
|
||||||
|
#define LOOK_AHEAD_FUTURE 15
|
||||||
#endif
|
#endif
|
||||||
|
|
22
GCodes.h
22
GCodes.h
|
@ -43,6 +43,8 @@ class GCodeBuffer
|
||||||
int readPointer;
|
int readPointer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//****************************************************************************************************
|
||||||
|
|
||||||
// The GCode interpreter
|
// The GCode interpreter
|
||||||
|
|
||||||
class GCodes
|
class GCodes
|
||||||
|
@ -61,7 +63,7 @@ class GCodes
|
||||||
|
|
||||||
boolean ActOnGcode(GCodeBuffer* gb);
|
boolean ActOnGcode(GCodeBuffer* gb);
|
||||||
boolean SetUpMove(GCodeBuffer* gb);
|
boolean SetUpMove(GCodeBuffer* gb);
|
||||||
boolean doDwell(GCodeBuffer *gb);
|
boolean DoDwell(GCodeBuffer *gb);
|
||||||
Platform* platform;
|
Platform* platform;
|
||||||
boolean active;
|
boolean active;
|
||||||
Webserver* webserver;
|
Webserver* webserver;
|
||||||
|
@ -69,8 +71,8 @@ class GCodes
|
||||||
boolean dwellWaiting;
|
boolean dwellWaiting;
|
||||||
GCodeBuffer* webGCode;
|
GCodeBuffer* webGCode;
|
||||||
GCodeBuffer* fileGCode;
|
GCodeBuffer* fileGCode;
|
||||||
boolean webGCodePending;
|
boolean webGCodeFinished;
|
||||||
boolean fileGCodePending;
|
boolean fileGCodeFinished;
|
||||||
boolean moveAvailable;
|
boolean moveAvailable;
|
||||||
boolean heatAvailable;
|
boolean heatAvailable;
|
||||||
float moveBuffer[DRIVES+1]; // Last is feedrate
|
float moveBuffer[DRIVES+1]; // Last is feedrate
|
||||||
|
@ -83,4 +85,18 @@ class GCodes
|
||||||
int fileToPrint;
|
int fileToPrint;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//*****************************************************************************************************
|
||||||
|
|
||||||
|
// Get an Int after a G Code letter
|
||||||
|
|
||||||
|
inline int GCodeBuffer::GetIValue()
|
||||||
|
{
|
||||||
|
return (int)GetLValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline char* GCodeBuffer::Buffer()
|
||||||
|
{
|
||||||
|
return gcodeBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
41
GCodes.ino
41
GCodes.ino
|
@ -39,8 +39,8 @@ void GCodes::Init()
|
||||||
{
|
{
|
||||||
webGCode->Init();
|
webGCode->Init();
|
||||||
fileGCode->Init();
|
fileGCode->Init();
|
||||||
webGCodePending = false;
|
webGCodeFinished = true;
|
||||||
fileGCodePending = false;
|
fileGCodeFinished = true;
|
||||||
active = true;
|
active = true;
|
||||||
moveAvailable = false;
|
moveAvailable = false;
|
||||||
heatAvailable = false;
|
heatAvailable = false;
|
||||||
|
@ -61,22 +61,22 @@ void GCodes::Spin()
|
||||||
if(!active)
|
if(!active)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(webGCodePending)
|
if(!webGCodeFinished)
|
||||||
{
|
{
|
||||||
webGCodePending = !ActOnGcode(webGCode);
|
webGCodeFinished = ActOnGcode(webGCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fileGCodePending)
|
if(!fileGCodeFinished)
|
||||||
{
|
{
|
||||||
fileGCodePending = !ActOnGcode(fileGCode);
|
fileGCodeFinished = ActOnGcode(fileGCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(webserver->GCodeAvailable())
|
if(webserver->GCodeAvailable())
|
||||||
{
|
{
|
||||||
if(webGCode->Put(webserver->ReadGCode()))
|
if(webGCode->Put(webserver->ReadGCode()))
|
||||||
webGCodePending = !ActOnGcode(webGCode);
|
webGCodeFinished = ActOnGcode(webGCode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,9 +86,11 @@ void GCodes::Spin()
|
||||||
if(platform->Read(fileBeingPrinted, b))
|
if(platform->Read(fileBeingPrinted, b))
|
||||||
{
|
{
|
||||||
if(fileGCode->Put(b))
|
if(fileGCode->Put(b))
|
||||||
fileGCodePending = !ActOnGcode(fileGCode);
|
fileGCodeFinished = ActOnGcode(fileGCode);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
|
if(fileGCode->Put('\n')) // In case there wasn't one in the file
|
||||||
|
fileGCodeFinished = ActOnGcode(fileGCode);
|
||||||
platform->Close(fileBeingPrinted);
|
platform->Close(fileBeingPrinted);
|
||||||
fileBeingPrinted = -1;
|
fileBeingPrinted = -1;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +99,8 @@ void GCodes::Spin()
|
||||||
|
|
||||||
// Move expects all axis movements to be absolute, and all
|
// Move expects all axis movements to be absolute, and all
|
||||||
// extruder drive moves to be relative. This function serves that.
|
// extruder drive moves to be relative. This function serves that.
|
||||||
|
// If the Move class can't receive the move (i.e. things have to wait)
|
||||||
|
// this returns false, otherwise true.
|
||||||
|
|
||||||
boolean GCodes::SetUpMove(GCodeBuffer *gb)
|
boolean GCodes::SetUpMove(GCodeBuffer *gb)
|
||||||
{
|
{
|
||||||
|
@ -154,7 +158,7 @@ void GCodes::QueueFileToPrint(char* fileName)
|
||||||
// Function to handle dwell delays. Return true for
|
// Function to handle dwell delays. Return true for
|
||||||
// Dwell finished, false otherwise.
|
// Dwell finished, false otherwise.
|
||||||
|
|
||||||
boolean GCodes::doDwell(GCodeBuffer *gb)
|
boolean GCodes::DoDwell(GCodeBuffer *gb)
|
||||||
{
|
{
|
||||||
unsigned long dwell;
|
unsigned long dwell;
|
||||||
|
|
||||||
|
@ -187,6 +191,9 @@ boolean GCodes::doDwell(GCodeBuffer *gb)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the GCode to act on is completed, this returns true,
|
||||||
|
// otherwise false.
|
||||||
|
|
||||||
boolean GCodes::ActOnGcode(GCodeBuffer *gb)
|
boolean GCodes::ActOnGcode(GCodeBuffer *gb)
|
||||||
{
|
{
|
||||||
int code;
|
int code;
|
||||||
|
@ -204,7 +211,7 @@ boolean GCodes::ActOnGcode(GCodeBuffer *gb)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: // Dwell
|
case 4: // Dwell
|
||||||
result = doDwell(gb);
|
result = DoDwell(gb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 10: // Set offsets
|
case 10: // Set offsets
|
||||||
|
@ -333,6 +340,8 @@ boolean GCodes::ActOnGcode(GCodeBuffer *gb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An empty buffer jumps straight here and gets disgarded
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -434,16 +443,6 @@ long GCodeBuffer::GetLValue()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get an Int after a G Code letter
|
|
||||||
|
|
||||||
int GCodeBuffer::GetIValue()
|
|
||||||
{
|
|
||||||
return (int)GetLValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
char* GCodeBuffer::Buffer()
|
|
||||||
{
|
|
||||||
return gcodeBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
75
Move.h
75
Move.h
|
@ -62,6 +62,30 @@ class DDA
|
||||||
volatile boolean active;
|
volatile boolean active;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LookAhead
|
||||||
|
{
|
||||||
|
friend class Move;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LookAhead(Move* m, Platform* p, LookAhead* n);
|
||||||
|
LookAhead* Next();
|
||||||
|
LookAhead* Previous();
|
||||||
|
void Init(float m[], float uu, float vv);
|
||||||
|
void SetUV(float uu, float vv);
|
||||||
|
float* Movement();
|
||||||
|
float U();
|
||||||
|
float V();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Move* move;
|
||||||
|
Platform* platform;
|
||||||
|
LookAhead* next;
|
||||||
|
LookAhead* previous;
|
||||||
|
float Cosine(LookAhead* a);
|
||||||
|
float movement[DRIVES+1]; // Last is feedrate
|
||||||
|
float u, v;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Move
|
class Move
|
||||||
{
|
{
|
||||||
|
@ -87,6 +111,10 @@ class Move
|
||||||
boolean DDARingFull();
|
boolean DDARingFull();
|
||||||
boolean GetDDARingLock();
|
boolean GetDDARingLock();
|
||||||
void ReleaseDDARingLock();
|
void ReleaseDDARingLock();
|
||||||
|
boolean LookAheadRingEmpty();
|
||||||
|
boolean LookAheadRingFull();
|
||||||
|
boolean LookAheadRingAdd(float m[], float uu, float vv);
|
||||||
|
LookAhead* LookAheadRingGet();
|
||||||
|
|
||||||
Platform* platform;
|
Platform* platform;
|
||||||
GCodes* gCodes;
|
GCodes* gCodes;
|
||||||
|
@ -96,6 +124,10 @@ class Move
|
||||||
DDA* ddaRingGetPointer;
|
DDA* ddaRingGetPointer;
|
||||||
volatile boolean ddaRingLocked;
|
volatile boolean ddaRingLocked;
|
||||||
|
|
||||||
|
LookAhead* lookAheadRingAddPointer;
|
||||||
|
LookAhead* lookAheadRingGetPointer;
|
||||||
|
DDA* lookAheadDDA;
|
||||||
|
|
||||||
unsigned long lastTime;
|
unsigned long lastTime;
|
||||||
boolean active;
|
boolean active;
|
||||||
boolean moveWaiting;
|
boolean moveWaiting;
|
||||||
|
@ -118,6 +150,37 @@ inline DDA* DDA::Next()
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline LookAhead* LookAhead::Next()
|
||||||
|
{
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline LookAhead* LookAhead::Previous()
|
||||||
|
{
|
||||||
|
return previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void LookAhead::SetUV(float uu, float vv)
|
||||||
|
{
|
||||||
|
u = uu;
|
||||||
|
v = vv;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float* LookAhead::Movement()
|
||||||
|
{
|
||||||
|
return movement;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float LookAhead::U()
|
||||||
|
{
|
||||||
|
return u;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float LookAhead::V()
|
||||||
|
{
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
inline boolean Move::DDARingEmpty()
|
inline boolean Move::DDARingEmpty()
|
||||||
{
|
{
|
||||||
return ddaRingGetPointer == ddaRingAddPointer;
|
return ddaRingGetPointer == ddaRingAddPointer;
|
||||||
|
@ -130,6 +193,18 @@ inline boolean Move::DDARingFull()
|
||||||
return ddaRingGetPointer->Next()->Next() == ddaRingAddPointer;
|
return ddaRingGetPointer->Next()->Next() == ddaRingAddPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline boolean Move::LookAheadRingEmpty()
|
||||||
|
{
|
||||||
|
return lookAheadRingGetPointer == lookAheadRingAddPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leave a gap of 2 as the last Get result may still be being processed
|
||||||
|
|
||||||
|
inline boolean Move::LookAheadRingFull()
|
||||||
|
{
|
||||||
|
return lookAheadRingGetPointer->Next()->Next() == lookAheadRingAddPointer;
|
||||||
|
}
|
||||||
|
|
||||||
inline boolean Move::GetDDARingLock()
|
inline boolean Move::GetDDARingLock()
|
||||||
{
|
{
|
||||||
if(ddaRingLocked)
|
if(ddaRingLocked)
|
||||||
|
|
98
Move.ino
98
Move.ino
|
@ -22,6 +22,7 @@ Licence: GPL
|
||||||
|
|
||||||
Move::Move(Platform* p, GCodes* g)
|
Move::Move(Platform* p, GCodes* g)
|
||||||
{
|
{
|
||||||
|
char i;
|
||||||
active = false;
|
active = false;
|
||||||
platform = p;
|
platform = p;
|
||||||
gCodes = g;
|
gCodes = g;
|
||||||
|
@ -30,11 +31,28 @@ Move::Move(Platform* p, GCodes* g)
|
||||||
|
|
||||||
ddaRingAddPointer = new DDA(this, platform, NULL);
|
ddaRingAddPointer = new DDA(this, platform, NULL);
|
||||||
dda = ddaRingAddPointer;
|
dda = ddaRingAddPointer;
|
||||||
for(char i = 1; i < RING_LENGTH; i++)
|
for(i = 1; i < RING_LENGTH; i++)
|
||||||
dda = new DDA(this, platform, dda);
|
dda = new DDA(this, platform, dda);
|
||||||
ddaRingAddPointer->next = dda;
|
ddaRingAddPointer->next = dda;
|
||||||
|
|
||||||
dda = NULL;
|
dda = NULL;
|
||||||
|
|
||||||
|
lookAheadRingAddPointer = new LookAhead(this, platform, NULL);
|
||||||
|
lookAheadRingGetPointer = lookAheadRingAddPointer;
|
||||||
|
for(i = 1; i < RING_LENGTH; i++)
|
||||||
|
lookAheadRingGetPointer = new LookAhead(this, platform, lookAheadRingGetPointer);
|
||||||
|
lookAheadRingAddPointer->next = lookAheadRingGetPointer;
|
||||||
|
|
||||||
|
lookAheadRingGetPointer = lookAheadRingAddPointer;
|
||||||
|
for(i = 0; i < RING_LENGTH; i++)
|
||||||
|
{
|
||||||
|
lookAheadRingAddPointer = lookAheadRingAddPointer->Next();
|
||||||
|
lookAheadRingAddPointer->previous = lookAheadRingGetPointer;
|
||||||
|
lookAheadRingGetPointer = lookAheadRingAddPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
lookAheadDDA = new DDA(this, platform, NULL);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Move::Init()
|
void Move::Init()
|
||||||
|
@ -46,11 +64,13 @@ void Move::Init()
|
||||||
for(i = 0; i <= AXES; i++)
|
for(i = 0; i <= AXES; i++)
|
||||||
currentPosition[i] = 0.0;
|
currentPosition[i] = 0.0;
|
||||||
|
|
||||||
// Empty the ring
|
// Empty the rings
|
||||||
|
|
||||||
ddaRingGetPointer = ddaRingAddPointer;
|
ddaRingGetPointer = ddaRingAddPointer;
|
||||||
ddaRingLocked = false;
|
ddaRingLocked = false;
|
||||||
|
|
||||||
|
lookAheadRingGetPointer = lookAheadRingAddPointer;
|
||||||
|
|
||||||
// The stepDistances arrays are look-up tables of the Euclidean distance
|
// The stepDistances arrays are look-up tables of the Euclidean distance
|
||||||
// between the start and end of a step. If the step is just along one axis,
|
// between the start and end of a step. If the step is just along one axis,
|
||||||
// it's just that axis's step length. If it's more, it is a Pythagoran
|
// it's just that axis's step length. If it's more, it is a Pythagoran
|
||||||
|
@ -227,6 +247,27 @@ void Move::Interrupt()
|
||||||
dda = NULL;
|
dda = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean Move::LookAheadRingAdd(float m[], float uu, float vv)
|
||||||
|
{
|
||||||
|
if(LookAheadRingFull())
|
||||||
|
return false;
|
||||||
|
lookAheadRingAddPointer->Init(m, uu, vv);
|
||||||
|
lookAheadRingAddPointer = lookAheadRingAddPointer->Next();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LookAhead* Move::LookAheadRingGet()
|
||||||
|
{
|
||||||
|
LookAhead* result;
|
||||||
|
if(LookAheadRingEmpty())
|
||||||
|
return NULL;
|
||||||
|
result = lookAheadRingGetPointer;
|
||||||
|
lookAheadRingGetPointer = lookAheadRingGetPointer->Next();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
boolean Move::AllMovesFinished()
|
boolean Move::AllMovesFinished()
|
||||||
{
|
{
|
||||||
// TODO - put some code in here
|
// TODO - put some code in here
|
||||||
|
@ -240,16 +281,15 @@ boolean Move::AllMovesFinished()
|
||||||
void Move::InterruptTime()
|
void Move::InterruptTime()
|
||||||
{
|
{
|
||||||
char buffer[50];
|
char buffer[50];
|
||||||
DDA* ddax = new DDA(this, platform, NULL);
|
|
||||||
float a[] = {1.0, 2.0, 3.0, 4.0, 5.0};
|
float a[] = {1.0, 2.0, 3.0, 4.0, 5.0};
|
||||||
float b[] = {2.0, 3.0, 4.0, 5.0, 6.0};
|
float b[] = {2.0, 3.0, 4.0, 5.0, 6.0};
|
||||||
float u = 50;
|
float u = 50;
|
||||||
float v = 50;
|
float v = 50;
|
||||||
ddax->Init(a, b, u, v);
|
lookAheadDDA->Init(a, b, u, v);
|
||||||
ddax->Start(false);
|
lookAheadDDA->Start(false);
|
||||||
unsigned long t = platform->Time();
|
unsigned long t = platform->Time();
|
||||||
for(long i = 0; i < 100000; i++)
|
for(long i = 0; i < 100000; i++)
|
||||||
ddax->Step(false);
|
lookAheadDDA->Step(false);
|
||||||
t = platform->Time() - t;
|
t = platform->Time() - t;
|
||||||
platform->Message(HOST_MESSAGE, "Time for 100000 calls of the interrupt function: ");
|
platform->Message(HOST_MESSAGE, "Time for 100000 calls of the interrupt function: ");
|
||||||
sprintf(buffer, "%ld", t);
|
sprintf(buffer, "%ld", t);
|
||||||
|
@ -552,5 +592,51 @@ void DDA::Step(boolean noTest)
|
||||||
platform->SetInterrupt(STANDBY_INTERRUPT_RATE);
|
platform->SetInterrupt(STANDBY_INTERRUPT_RATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//***************************************************************************************************
|
||||||
|
|
||||||
|
LookAhead::LookAhead(Move* m, Platform* p, LookAhead* n)
|
||||||
|
{
|
||||||
|
move = m;
|
||||||
|
platform = p;
|
||||||
|
next = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LookAhead::Init(float m[], float uu, float vv)
|
||||||
|
{
|
||||||
|
u = uu;
|
||||||
|
v = vv;
|
||||||
|
for(char i = 0; i <= DRIVES; i++)
|
||||||
|
movement[i] = m[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// This returns the cosine of the angle between
|
||||||
|
// the movement starting at start, and the movement
|
||||||
|
// starting at the end of that. Note that it
|
||||||
|
// includes Z movements, though Z values will almost always
|
||||||
|
// not change.
|
||||||
|
|
||||||
|
float LookAhead::Cosine(LookAhead* start)
|
||||||
|
{
|
||||||
|
LookAhead* n1 = start->Next();
|
||||||
|
LookAhead* n2 = n1->Next();
|
||||||
|
float sum = 0.0;
|
||||||
|
float a2 = 0.0;
|
||||||
|
float b2 = 0.0;
|
||||||
|
float m1;
|
||||||
|
float m2;
|
||||||
|
for(char i = 0; i < AXES; i++)
|
||||||
|
{
|
||||||
|
m1 = n1->movement[i] - start->movement[i];
|
||||||
|
m2 = n2->movement[i] - n1->movement[i];
|
||||||
|
a2 += m1*m1;
|
||||||
|
b2 += m2*m2;
|
||||||
|
sum += m1*m2;
|
||||||
|
}
|
||||||
|
sum = sum/( (float)sqrt(a2) * (float)sqrt(b2) );
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ RepRap self-replicating 3D printers.
|
||||||
|
|
||||||
It owes a lot to Marlin and to the original RepRap FiveD_GCode.
|
It owes a lot to Marlin and to the original RepRap FiveD_GCode.
|
||||||
|
|
||||||
|
|
||||||
General design principles:
|
General design principles:
|
||||||
|
|
||||||
* Control by RepRap G Codes. These are taken to be machine independent, though some may be unsupported.
|
* Control by RepRap G Codes. These are taken to be machine independent, though some may be unsupported.
|
||||||
|
@ -24,6 +25,76 @@ General design principles:
|
||||||
* Don't avoid pointers,
|
* Don't avoid pointers,
|
||||||
* Use operator and function overloading where appropriate, particularly for vector algebra.
|
* Use operator and function overloading where appropriate, particularly for vector algebra.
|
||||||
|
|
||||||
|
|
||||||
|
Naming conventions:
|
||||||
|
|
||||||
|
* #defines are all capitals with optional underscores between words
|
||||||
|
* No underscores in other names - make readable with capitalisation: MakeReadableWithCapitalisation
|
||||||
|
* Classes and functions start with a capital letter
|
||||||
|
* Variables start with a lower case letter
|
||||||
|
|
||||||
|
|
||||||
|
Structure:
|
||||||
|
|
||||||
|
There are six main classes:
|
||||||
|
|
||||||
|
* RepRap
|
||||||
|
* GCodes
|
||||||
|
* Heat
|
||||||
|
* Move
|
||||||
|
* Platform, and
|
||||||
|
* Webserver
|
||||||
|
|
||||||
|
RepRap:
|
||||||
|
|
||||||
|
This is just a container class for the single instances of all the others, and otherwise does very little.
|
||||||
|
|
||||||
|
GCodes:
|
||||||
|
|
||||||
|
This class is fed GCodes, either from the web interface or from GCode files, interprests them, and requests
|
||||||
|
actions from the RepRap machine via the other classes.
|
||||||
|
|
||||||
|
Heat:
|
||||||
|
|
||||||
|
This class imlements all heating and temperature control in the RepRap machine.
|
||||||
|
|
||||||
|
Move:
|
||||||
|
|
||||||
|
This class controls all movement of the RepRap machine, both along its axes, and in its extruder drives.
|
||||||
|
|
||||||
|
Platform:
|
||||||
|
|
||||||
|
This is the only class that knows anything about the physical setup of the RepRap machine and its
|
||||||
|
controlling electronics. It implements the interface between all the other classes and the RepRap machine.
|
||||||
|
All the other classes are completely machine-independent (though they may declare arrays dimensioned
|
||||||
|
to values #defined in Platform.h).
|
||||||
|
|
||||||
|
Webserver:
|
||||||
|
|
||||||
|
This class talks to the network (via Platform) and implements a simple webserver to give an interactive
|
||||||
|
interface to the RepRap machine. It uses the Knockout and Jquery Javascript libraries to achieve this.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
When the software is running there is one single instance of each class, and all the memory allocation is
|
||||||
|
done on initialisation. new/malloc should not be used in the general running code, and delete is never
|
||||||
|
used. Each class has an Init() function that resets it to its boot-up state; the constructors merely handle
|
||||||
|
that memory allocation on startup. Calling RepRap.Init() calls all the other Init()s in the right sequence.
|
||||||
|
|
||||||
|
There are other ancilliary classes that are declared in the .h files for the master classes that use them. For
|
||||||
|
example, Move has a DDA class that implements a Bresenham/digital differential analyser.
|
||||||
|
|
||||||
|
All the main classes have a Spin() function. These are called in a loop by the RepRap.Spin() function and implement
|
||||||
|
simple timesharing. No class does, or ever should, wait inside one of its functions for anything to happen or call
|
||||||
|
any sort of delay() function. The general rule is:
|
||||||
|
|
||||||
|
Can I do a thing?
|
||||||
|
Yes - do it
|
||||||
|
No - set a flag/timer to remind me to do it next-time-I'm-called/at-a-future-time and return.
|
||||||
|
|
||||||
|
Note that it is simple to raise the "priority" of any class's activities relative to the others by calling its
|
||||||
|
Spin() function more than once from RepRap.Spin().
|
||||||
|
|
||||||
-----------------------------------------------------------------------------------------------------
|
-----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
Version 0.1
|
Version 0.1
|
||||||
|
|
Reference in a new issue