diff --git a/GCodes.h b/GCodes.h index b0c0d05..56ff118 100644 --- a/GCodes.h +++ b/GCodes.h @@ -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 diff --git a/GCodes.ino b/GCodes.ino index 0da10c5..0efbc70 100644 --- a/GCodes.ino +++ b/GCodes.ino @@ -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; diff --git a/Move.h b/Move.h index 796aa7f..e270057 100644 --- a/Move.h +++ b/Move.h @@ -74,6 +74,7 @@ class Move void Qmove(); void GetCurrentState(float m[]); void Interrupt(); + boolean AllMovesFinished(); void InterruptTime(); friend class DDA; diff --git a/Move.ino b/Move.ino index ebfabdd..4e41f4a 100644 --- a/Move.ino +++ b/Move.ino @@ -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. diff --git a/Platform.h b/Platform.h index 0193a96..2b4a2e7 100644 --- a/Platform.h +++ b/Platform.h @@ -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; } diff --git a/Platform.ino b/Platform.ino index e90cd55..93f56cd 100644 --- a/Platform.ino +++ b/Platform.ino @@ -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); diff --git a/SD-image/gcodes/square.g b/SD-image/gcodes/square.g new file mode 100644 index 0000000..1869b66 --- /dev/null +++ b/SD-image/gcodes/square.g @@ -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 + diff --git a/SD-image/gcodes/square.g~ b/SD-image/gcodes/square.g~ new file mode 100644 index 0000000..e69de29 diff --git a/Webserver.ino b/Webserver.ino index bc45e17..d72c0e7 100644 --- a/Webserver.ino +++ b/Webserver.ino @@ -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()