This repository has been archived on 2025-02-01. You can view files and clone it, but cannot push or open issues or pull requests.
reprapfirmware-dc42/src/GCodes/GCodeQueue.cpp
David Crocker 7a05e499fc Version 1.18.2
Support new production DueX5 and DueX2 boards and Fan 8
Fix M21
Queue M42 commands
Fix M106 incorrect P parameter check
2017-06-16 13:39:28 +01:00

234 lines
4.9 KiB
C++

/*
* GCodeQueue.cpp
*
* Created on: 22 Jun 2016
* Author: Christian
*/
#include "GCodeQueue.h"
#include "RepRap.h"
#include "GCodes.h"
#include "Movement/Move.h"
// GCodeQueue class
GCodeQueue::GCodeQueue() : freeItems(nullptr), queuedItems(nullptr)
{
for(size_t i = 0; i < maxQueuedCodes; i++)
{
freeItems = new QueuedCode(freeItems);
}
}
bool GCodeQueue::QueueCode(GCodeBuffer &gb, uint32_t segmentsLeft)
{
// Don't queue anything if no moves are being performed
uint32_t scheduledMoves = reprap.GetMove()->GetScheduledMoves() + segmentsLeft;
if (scheduledMoves == reprap.GetMove()->GetCompletedMoves())
{
return false;
}
#if SUPPORT_ROLAND
// Don't queue codes if the Roland module is active
if (reprap.GetRoland()->Active())
{
return false;
}
#endif
// Check for G-Codes that can be queued
bool queueCode = false;
switch (gb.GetCommandLetter())
{
case 'G':
{
const int code = gb.GetIValue();
// Set active/standby temperatures
queueCode = (code == 10 && gb.Seen('P'));
}
break;
case 'M':
{
const int code = gb.GetIValue();
switch(code)
{
case 3: // spindle control
case 4:
case 5:
case 42: // set IO pin
case 106: // fan control
case 107:
case 104: // set temperatures and return immediately
case 140:
case 141:
case 144:
case 117: // display message
case 280: // set servo
case 300: // beep
case 420: // set RGB colour
queueCode = true;
break;
default:
break;
}
}
break;
}
// Does it make sense to queue this code?
if (queueCode)
{
char codeToRun[GCODE_LENGTH];
size_t codeToRunLength;
// Can we queue this code somewhere?
if (freeItems == nullptr)
{
// No - we've run out of free items. Run the first outstanding code
queueCode = false;
codeToRunLength = strlen(queuedItems->code);
strncpy(codeToRun, queuedItems->code, codeToRunLength);
codeToRun[ARRAY_UPB(codeToRun)] = 0;
// Release the first queued item so that it can be reused later
QueuedCode *item = queuedItems;
queuedItems = item->next;
item->next = nullptr;
freeItems = item;
}
// Unlink a free element and assign gb's code to it
QueuedCode *code = freeItems;
freeItems = code->next;
code->AssignFrom(gb);
code->executeAtMove = scheduledMoves;
// Append it to the list of queued codes
if (queuedItems == nullptr)
{
queuedItems = code;
}
else
{
QueuedCode *last = queuedItems;
while (last->Next() != nullptr)
{
last = last->Next();
}
last->next = code;
}
code->next = nullptr;
// Overwrite the passed gb's content if we could not store its original code
if (!queueCode && !gb.Put(codeToRun, codeToRunLength))
{
gb.Put('\n');
}
}
return queueCode;
}
bool GCodeQueue::FillBuffer(GCodeBuffer *gb)
{
// Can this buffer be filled?
if (queuedItems == nullptr || queuedItems->executeAtMove > reprap.GetMove()->GetCompletedMoves())
{
// No - stop here
return false;
}
// Yes - load it into the passed GCodeBuffer instance
QueuedCode *code = queuedItems;
code->AssignTo(gb);
// Release this item again
queuedItems = queuedItems->next;
code->next = freeItems;
freeItems = code;
return true;
}
// Because some moves may end before the print is actually paused, we need a method to
// remove all the entries that will not be executed after the print has finally paused
void GCodeQueue::PurgeEntries()
{
QueuedCode *item = queuedItems, *lastItem = nullptr;
while (item != nullptr)
{
if (item->executeAtMove > reprap.GetMove()->GetScheduledMoves())
{
// Release this item
QueuedCode *nextItem = item->Next();
item->next = freeItems;
freeItems = item;
// Unlink it from the list
if (lastItem == nullptr)
{
queuedItems = nextItem;
}
else
{
lastItem->next = nextItem;
}
item = nextItem;
}
else
{
lastItem = item;
item = item->Next();
}
}
}
void GCodeQueue::Clear()
{
while (queuedItems != nullptr)
{
QueuedCode *item = queuedItems;
queuedItems = item->Next();
item->next = freeItems;
freeItems = item;
}
}
void GCodeQueue::Diagnostics(MessageType mtype)
{
reprap.GetPlatform()->MessageF(mtype, "Code queue is %s\n", (queuedItems == nullptr) ? "empty." : "not empty:");
if (queuedItems != nullptr)
{
QueuedCode *item = queuedItems;
size_t queueLength = 0;
do
{
queueLength++;
reprap.GetPlatform()->MessageF(mtype, "Queued '%s' for move %d\n", item->code, item->executeAtMove);
} while ((item = item->Next()) != nullptr);
reprap.GetPlatform()->MessageF(mtype, "%d of %d codes have been queued.\n", queueLength, maxQueuedCodes);
}
}
// QueuedCode class
void QueuedCode::AssignFrom(GCodeBuffer &gb)
{
toolNumberAdjust = gb.GetToolNumberAdjust();
strncpy(code, gb.Buffer(), GCODE_LENGTH);
code[ARRAY_UPB(code)] = 0;
}
void QueuedCode::AssignTo(GCodeBuffer *gb)
{
gb->SetToolNumberAdjust(toolNumberAdjust);
if (!gb->Put(code, strlen(code)))
{
gb->Put('\n');
}
}