Printing G Code files implemented.

This commit is contained in:
Adrian Bowyer 2013-05-27 20:51:32 +01:00
parent 30767c8f62
commit 9b0d714a3a
9 changed files with 194 additions and 73 deletions

View file

@ -33,6 +33,7 @@ class GCodeBuffer
boolean Seen(char c);
float GetFValue();
int GetIValue();
long GetLValue();
char* Buffer();
private:
@ -58,14 +59,18 @@ class GCodes
private:
void ActOnGcode(GCodeBuffer* gb);
boolean ActOnGcode(GCodeBuffer* gb);
void SetUpMove(GCodeBuffer* gb);
boolean doDwell(GCodeBuffer *gb);
Platform* platform;
boolean active;
Webserver* webserver;
unsigned long lastTime;
unsigned long dwellTime;
boolean dwellWaiting;
GCodeBuffer* webGCode;
GCodeBuffer* fileGCode;
boolean webGCodePending;
boolean fileGCodePending;
boolean moveAvailable;
boolean heatAvailable;
float moveBuffer[DRIVES+1]; // Last is feedrate
@ -74,6 +79,8 @@ class GCodes
char gCodeLetters[DRIVES + 1]; // Extra is for F
float lastPos[DRIVES - AXES]; // Just needed for relative moves.
float distanceScale;
int fileBeingPrinted;
int fileToPrint;
};
#endif

View file

@ -37,9 +37,10 @@ void GCodes::Exit()
void GCodes::Init()
{
lastTime = platform->Time();
webGCode->Init();
fileGCode->Init();
webGCodePending = false;
fileGCodePending = false;
active = true;
moveAvailable = false;
heatAvailable = false;
@ -49,6 +50,49 @@ void GCodes::Init()
distanceScale = 1.0;
for(char i = 0; i < DRIVES - AXES; i++)
lastPos[i] = 0.0;
fileBeingPrinted = -1;
fileToPrint = -1;
dwellWaiting = false;
dwellTime = platform->Time();
}
void GCodes::Spin()
{
if(!active)
return;
if(webGCodePending)
{
webGCodePending = !ActOnGcode(webGCode);
return;
}
if(fileGCodePending)
{
fileGCodePending = !ActOnGcode(fileGCode);
return;
}
if(webserver->GCodeAvailable())
{
if(webGCode->Put(webserver->ReadGCode()))
webGCodePending = !ActOnGcode(webGCode);
return;
}
if(fileBeingPrinted >= 0)
{
unsigned char b;
if(platform->Read(fileBeingPrinted, b))
{
if(fileGCode->Put(b))
fileGCodePending = !ActOnGcode(fileGCode);
} else
{
platform->Close(fileBeingPrinted);
fileBeingPrinted = -1;
}
}
}
// Move expects all axis movements to be absolute, and all
@ -101,12 +145,51 @@ void GCodes::SetUpMove(GCodeBuffer *gb)
void GCodes::QueueFileToPrint(char* fileName)
{
platform->Message(HOST_MESSAGE, "File queued for printing.\n");
fileToPrint = platform->OpenFile(platform->GetGCodeDir(), fileName, false);
}
void GCodes::ActOnGcode(GCodeBuffer *gb)
// Function to handle dwell delays. Return true for
// Dwell finished, false otherwise.
boolean GCodes::doDwell(GCodeBuffer *gb)
{
unsigned long dwell;
if(gb->Seen('P'))
dwell = 1000ul*(unsigned long)gb->GetLValue(); // P values are in milliseconds; we need microseconds
else
return true; // No time given - throw it away
// Wait for all the queued moves to stop
if(!reprap.GetMove()->AllMovesFinished())
return false;
// Are we already in a dwell?
if(dwellWaiting)
{
if((long)(platform->Time() - dwellTime) >= 0)
{
dwellWaiting = false;
return true;
}
return false;
}
// New dwell - set it up
dwellWaiting = true;
dwellTime = platform->Time() + dwell;
return false;
}
boolean GCodes::ActOnGcode(GCodeBuffer *gb)
{
int code;
boolean result = true;
unsigned long dwell;
if(gb->Seen('G'))
{
@ -119,7 +202,7 @@ void GCodes::ActOnGcode(GCodeBuffer *gb)
break;
case 4: // Dwell
platform->Message(HOST_MESSAGE, "Dwell received\n");
result = doDwell(gb);
break;
case 10: // Set offsets
@ -157,7 +240,7 @@ void GCodes::ActOnGcode(GCodeBuffer *gb)
platform->Message(HOST_MESSAGE, gb->Buffer());
platform->Message(HOST_MESSAGE, "\n");
}
return;
return result;
}
if(gb->Seen('M'))
@ -179,7 +262,8 @@ void GCodes::ActOnGcode(GCodeBuffer *gb)
break;
case 24: // Print selected file
platform->Message(HOST_MESSAGE, "Print started\n");
fileBeingPrinted = fileToPrint;
fileToPrint = -1;
break;
case 82:
@ -223,7 +307,7 @@ void GCodes::ActOnGcode(GCodeBuffer *gb)
platform->Message(HOST_MESSAGE, gb->Buffer());
platform->Message(HOST_MESSAGE, "\n");
}
return;
return result;
}
if(gb->Seen('T'))
@ -247,24 +331,10 @@ void GCodes::ActOnGcode(GCodeBuffer *gb)
}
}
return result;
}
void GCodes::Spin()
{
if(!active)
return;
if(webserver->GCodeAvailable())
{
if(webGCode->Put(webserver->ReadGCode()))
ActOnGcode(webGCode);
}
// TODO - Add processing of GCodes from file
}
boolean GCodes::ReadMove(float* m)
{
@ -281,6 +351,8 @@ boolean GCodes::ReadHeat(float* h)
}
//*************************************************************************************
GCodeBuffer::GCodeBuffer(Platform* p)
{
platform = p;
@ -345,20 +417,28 @@ float GCodeBuffer::GetFValue()
return result;
}
// Get an Int after a G Code letter
int GCodeBuffer::GetIValue()
// Get an long after a G Code letter
long GCodeBuffer::GetLValue()
{
if(readPointer < 0)
{
platform->Message(HOST_MESSAGE, "GCodes: Attempt to read a GCode int before a search.\n");
return 0;
}
int result = (int)strtol(&gcodeBuffer[readPointer + 1], NULL, 0);
long result = strtol(&gcodeBuffer[readPointer + 1], NULL, 0);
readPointer = -1;
return result;
}
// Get an Int after a G Code letter
int GCodeBuffer::GetIValue()
{
return (int)GetLValue();
}
char* GCodeBuffer::Buffer()
{
return gcodeBuffer;

1
Move.h
View file

@ -74,6 +74,7 @@ class Move
void Qmove();
void GetCurrentState(float m[]);
void Interrupt();
boolean AllMovesFinished();
void InterruptTime();
friend class DDA;

View file

@ -223,6 +223,12 @@ void Move::Interrupt()
dda = NULL;
}
boolean Move::AllMovesFinished()
{
// TODO - put some code in here
return true;
}
// This function is never normally called. It is a test to time
// the interrupt function. To activate it, uncomment the line that calls
// this in Platform.ino.

View file

@ -184,7 +184,8 @@ class Platform
// Communications and data storage; opening something unsupported returns -1.
char* FileList(char* directory); // Returns a ,-separated list of all the files in the named directory (for example on an SD card).
int OpenFile(char* fileName, boolean write); // Open a local file (for example on an SD card).
//int OpenFile(char* fileName, boolean write); // Open a local file (for example on an SD card).
int OpenFile(char* directory, char* fileName, boolean write); // Open a local file (for example on an SD card).
void GoToEnd(int file); // Position the file at the end (so you can write on the end).
boolean Read(int file, unsigned char& b); // Read a single byte from a file into b,
// returned value is false for EoF, true otherwise
@ -192,12 +193,11 @@ class Platform
void Write(int file, char b); // Write the byte b to a file.
unsigned long Length(int file); // File size in bytes
char* GetWebDir(); // Where the htm etc files are
char* GetGcodeDir(); // Where the gcodes are
char* GetGCodeDir(); // Where the gcodes are
char* GetSysDir(); // Where the system files are
char* GetTempDir(); // Where temporary files are
void Close(int file); // Close a file or device, writing any unwritten buffer contents first.
boolean DeleteFile(char* fileName); // Delete a file
char* PrependRoot(char* result, char* root, char* fileName);
boolean DeleteFile(char* directory, char* fileName); // Delete a file
unsigned char ClientRead(); // Read a byte from the client
void SendToClient(char* message); // Send string to the host
@ -242,6 +242,8 @@ class Platform
void InitialiseInterrupts();
char* CombineName(char* result, char* directory, char* fileName);
RepRap* reprap;
// DRIVES
@ -286,6 +288,7 @@ class Platform
byte* buf[MAX_FILES];
int bPointer[MAX_FILES];
char fileList[FILE_LIST_LENGTH];
char scratchString[STRING_LENGTH];
// Network connection
@ -316,7 +319,7 @@ inline char* Platform::GetWebDir()
// Where the gcodes are
inline char* Platform::GetGcodeDir()
inline char* Platform::GetGCodeDir()
{
return gcodeDir;
}

View file

@ -58,27 +58,6 @@ inline void Platform::Interrupt()
reprap->Interrupt(); // Put nothing else in this function
}
/*
void startTimer(Tc *tc, uint32_t channel, IRQn_Type irq, uint32_t frequency)
{
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq);
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
// VARIANT_MCK = 84x10^6 for the Due
uint32_t rc = VARIANT_MCK/128/frequency; //128 because we selected TIMER_CLOCK4 above
TC_SetRA(tc, channel, rc/2); //50% high, 50% low
TC_SetRC(tc, channel, rc);
TC_Start(tc, channel);
tc->TC_CHANNEL[channel].TC_IER=TC_IER_CPCS;
tc->TC_CHANNEL[channel].TC_IDR=~TC_IER_CPCS;
NVIC_EnableIRQ(irq);
}
*/
//*******************************************************************************************************************
void Platform::Init()
@ -207,13 +186,13 @@ void Platform::Init()
active = true;
}
/*
char* Platform::PrependRoot(char* result, char* root, char* fileName)
{
strcpy(result, root);
return strcat(result, fileName);
}
*/
// Load settings from local storage; return true if successful, false otherwise
@ -277,6 +256,41 @@ void Platform::SetHeater(char heater, const float& power)
*/
char* Platform::CombineName(char* result, char* directory, char* fileName)
{
int out = 0;
int in = 0;
result[out] = '/';
out++;
if(directory != NULL)
{
if(directory[in] == '/')
in++;
while(directory[in] != 0 && directory[in] != '\n' && directory[in] != '/')
{
result[out] = directory[in];
out++;
in++;
}
}
result[out] = '/';
out++;
in = 0;
while(fileName[in] != 0 && fileName[in] != '\n' && fileName[in] != '/')
{
result[out] = fileName[in];
out++;
in++;
}
result[out] = 0;
return result;
}
// List the flat files in a directory. No sub-directories or recursion.
char* Platform::FileList(char* directory)
@ -317,15 +331,17 @@ char* Platform::FileList(char* directory)
}
// Delete a file
boolean Platform::DeleteFile(char* fileName)
boolean Platform::DeleteFile(char* directory, char* fileName)
{
return SD.remove(fileName);
CombineName(scratchString, directory, fileName);
return SD.remove(scratchString);
}
// Open a local file (for example on an SD card).
int Platform::OpenFile(char* fileName, boolean write)
int Platform::OpenFile(char* directory, char* fileName, boolean write)
{
CombineName(scratchString, directory, fileName);
int result = -1;
for(int i = 0; i < MAX_FILES; i++)
if(!inUse[i])
@ -339,7 +355,7 @@ int Platform::OpenFile(char* fileName, boolean write)
return -1;
}
if(!SD.exists(fileName))
if(!SD.exists(scratchString))
{
if(!write)
{
@ -348,16 +364,16 @@ int Platform::OpenFile(char* fileName, boolean write)
Message(HOST_MESSAGE, " not found for reading.\n");
return -1;
}
files[result] = SD.open(fileName, FILE_WRITE);
files[result] = SD.open(scratchString, FILE_WRITE);
bPointer[result] = 0;
} else
{
if(write)
{
files[result] = SD.open(fileName, FILE_WRITE);
files[result] = SD.open(scratchString, FILE_WRITE);
bPointer[result] = 0;
} else
files[result] = SD.open(fileName, FILE_READ);
files[result] = SD.open(scratchString, FILE_READ);
}
inUse[result] = true;
@ -469,7 +485,7 @@ void Platform::Message(char type, char* message)
default:
int m = OpenFile(PrependRoot(scratchString, GetWebDir(), MESSAGE_FILE), true);
int m = OpenFile(GetWebDir(), MESSAGE_FILE, true);
GoToEnd(m);
WriteString(m, message);
Serial.print(message);

9
SD-image/gcodes/square.g Normal file
View file

@ -0,0 +1,9 @@
G1 X55 Y5 F2000
G1 X55 Y55
G1 X5 Y55
G1 X5 Y5
G1 X55 Y5
G1 X55 Y55
G1 X5 Y55
G1 X5 Y5

View file

View file

@ -132,10 +132,10 @@ boolean Webserver::LoadGcodeBuffer(char* gc, boolean convertWeb)
if(StringStartsWith(gcodeBuffer, "M23 ")) fileAct |= 2;
if(fileAct) // Delete or print a file?
{
{
if(fileAct == 1) // Delete?
{
if(!platform->DeleteFile(platform->PrependRoot(scratchString, platform->GetGcodeDir(), &gcodeBuffer[4])))
if(!platform->DeleteFile(platform->GetGCodeDir(), &gcodeBuffer[4]))
{
platform->Message(HOST_MESSAGE, "Unsuccsessful attempt to delete: ");
platform->Message(HOST_MESSAGE, &gcodeBuffer[4]);
@ -143,12 +143,11 @@ boolean Webserver::LoadGcodeBuffer(char* gc, boolean convertWeb)
}
} else // Print it
{
reprap.GetGCodes()->QueueFileToPrint(platform->PrependRoot(scratchString, platform->GetGcodeDir(), &gcodeBuffer[4]));
reprap.GetGCodes()->QueueFileToPrint(&gcodeBuffer[4]);
}
// Check for further G Codes in the string
gcodePointer = 0;
while(gcodeBuffer[gcodePointer])
{
if(gcodeBuffer[gcodePointer] == '\n')
@ -199,11 +198,11 @@ void Webserver::SendFile(char* nameOfFileToSend)
if(jsonPointer < 0)
{
fileBeingSent = platform->OpenFile(platform->PrependRoot(scratchString, platform->GetWebDir(), nameOfFileToSend), false);
fileBeingSent = platform->OpenFile(platform->GetWebDir(), nameOfFileToSend, false);
if(fileBeingSent < 0)
{
nameOfFileToSend = FOUR04_FILE;
fileBeingSent = platform->OpenFile(platform->PrependRoot(scratchString, platform->GetWebDir(), nameOfFileToSend), false);
fileBeingSent = platform->OpenFile(platform->GetWebDir(), nameOfFileToSend, false);
}
writing = true;
}
@ -321,7 +320,7 @@ void Webserver::GetJsonResponse(char* request)
if(StringStartsWith(request, "files"))
{
char* fileList = platform->FileList(platform->GetGcodeDir());
char* fileList = platform->FileList(platform->GetGCodeDir());
strcpy(jsonResponse, "{\"files\":[");
strcat(jsonResponse, fileList);
strcat(jsonResponse, "]}");
@ -496,11 +495,11 @@ void Webserver::BlankLineFromClient()
if(receivingPost)
{
postFile = platform->OpenFile(platform->PrependRoot(scratchString, platform->GetGcodeDir(), postFileName), true);
postFile = platform->OpenFile(platform->GetGCodeDir(), postFileName, true);
if(postFile < 0 || !postBoundary[0])
{
platform->Message(HOST_MESSAGE, "Can't open file for write or no post boundary: ");
platform->Message(HOST_MESSAGE, platform->PrependRoot(scratchString, platform->GetGcodeDir(), postFileName));
platform->Message(HOST_MESSAGE, postFileName);
platform->Message(HOST_MESSAGE, "\n");
InitialisePost();
}
@ -626,7 +625,7 @@ void Webserver::Init()
// Reinitialise the message file
platform->DeleteFile(platform->PrependRoot(scratchString, platform->GetWebDir(), MESSAGE_FILE));
platform->DeleteFile(platform->GetWebDir(), MESSAGE_FILE);
}
void Webserver::Exit()