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/GCodes.ino

336 lines
6.6 KiB
C++

/****************************************************************************************************
RepRapFirmware - G Codes
This class interprets G Codes from one or more sources, and calls the functions in Move, Heat etc
that drive the machine to do what the G Codes command.
-----------------------------------------------------------------------------------------------------
Version 0.1
13 February 2013
Adrian Bowyer
RepRap Professional Ltd
http://reprappro.com
Licence: GPL
****************************************************************************************************/
#include "RepRapFirmware.h"
GCodes::GCodes(Platform* p, Webserver* w)
{
active = false;
platform = p;
webserver = w;
webGCode = new GCodeBuffer(platform);
fileGCode = new GCodeBuffer(platform);
}
void GCodes::Exit()
{
active = false;
}
void GCodes::Init()
{
lastTime = platform->Time();
webGCode->Init();
fileGCode->Init();
active = true;
moveAvailable = false;
heatAvailable = false;
drivesRelative = false;
axesRelative = false;
gCodeLetters = GCODE_LETTERS;
distanceScale = 1.0;
for(char i = 0; i < DRIVES - AXES; i++)
lastPos[i] = 0.0;
}
// Move expects all axis movements to be absolute, and all
// extruder drive moves to be relative. This function serves that.
void GCodes::SetUpMove(GCodeBuffer *gb)
{
// Load the last position
reprap.GetMove()->GetCurrentState(moveBuffer);
// What does the G Code say?
for(char i = 0; i < DRIVES; i++)
{
if(i < AXES)
{
if(gb->Seen(gCodeLetters[i]))
{
if(axesRelative)
moveBuffer[i] += gb->GetFValue()*distanceScale;
else
moveBuffer[i] = gb->GetFValue()*distanceScale;
}
} else
{
if(gb->Seen(gCodeLetters[i]))
{
if(drivesRelative)
moveBuffer[i] = gb->GetFValue()*distanceScale;
else
moveBuffer[i] = gb->GetFValue()*distanceScale - lastPos[i - AXES];
}
}
}
// Deal with feedrate
if(gb->Seen(gCodeLetters[DRIVES]))
moveBuffer[DRIVES] = gb->GetFValue()*distanceScale;
// Remember for next time if we are switched
// to absolute drive moves
for(char i = AXES; i < DRIVES; i++)
lastPos[i - AXES] = moveBuffer[i];
moveAvailable = true;
}
void GCodes::ActOnGcode(GCodeBuffer *gb)
{
int code;
if(gb->Seen('G'))
{
code = gb->GetIValue();
switch(code)
{
case 0: // There are no rapid moves...
case 1: // Ordinary move
SetUpMove(gb);
break;
case 4: // Dwell
break;
case 10: // Set offsets
break;
case 20: // Inches (which century are we living in, here?)
distanceScale = INCH_TO_MM;
break;
case 21: // mm
distanceScale = 1.0;
break;
case 28: // Home
break;
case 90: // Absolute coordinates
drivesRelative = false;
axesRelative = false;
break;
case 91: // Relative coordinates
drivesRelative = true;
axesRelative = true;
break;
case 92: // Set position
break;
default:
platform->Message(HOST_MESSAGE, "GCodes - invalid G Code: ");
platform->Message(HOST_MESSAGE, gb->Buffer());
platform->Message(HOST_MESSAGE, "<br>\n");
}
return;
}
if(gb->Seen('M'))
{
code = gb->GetIValue();
switch(code)
{
case 0: // Stop
case 1: // Sleep
break;
case 18: // Motors off ???
break;
case 82:
drivesRelative = false;
break;
case 83:
drivesRelative = true;
break;
case 106: // Fan on
break;
case 107: // Fan off
break;
case 116: // Wait for everything
break;
case 126: // Valve open
platform->Message(HOST_MESSAGE, "M126 - valves not yet implemented<br>\n");
break;
case 127: // Valve closed
platform->Message(HOST_MESSAGE, "M127 - valves not yet implemented<br>\n");
break;
case 140: // Set bed temperature
break;
case 141: // Chamber temperature
platform->Message(HOST_MESSAGE, "M141 - heated chamber not yet implemented<br>\n");
break;
default:
platform->Message(HOST_MESSAGE, "GCodes - invalid M Code: ");
platform->Message(HOST_MESSAGE, gb->Buffer());
platform->Message(HOST_MESSAGE, "<br>\n");
}
return;
}
if(gb->Seen('T'))
{
code = gb->GetIValue();
switch(code)
{
default:
platform->Message(HOST_MESSAGE, "GCodes - invalid T Code: ");
platform->Message(HOST_MESSAGE, gb->Buffer());
platform->Message(HOST_MESSAGE, "<br>\n");
}
}
}
void GCodes::Spin()
{
if(!active)
return;
if(webserver->Available())
{
if(webGCode->Put(webserver->Read()))
ActOnGcode(webGCode);
}
// TODO - Add processing of GCodes from file
}
boolean GCodes::ReadMove(float* m)
{
if(!moveAvailable)
return false;
for(char i = 0; i <= DRIVES; i++) // 1 more for F
m[i] = moveBuffer[i];
moveAvailable = false;
}
boolean GCodes::ReadHeat(float* h)
{
}
GCodeBuffer::GCodeBuffer(Platform* p)
{
platform = p;
}
void GCodeBuffer::Init()
{
gcodePointer = 0;
readPointer = -1;
}
boolean GCodeBuffer::Put(char c)
{
boolean result = false;
gcodeBuffer[gcodePointer] = c;
if(gcodeBuffer[gcodePointer] == '\n' || !gcodeBuffer[gcodePointer])
{
gcodeBuffer[gcodePointer] = 0;
gcodePointer = 0;
result = true;
} else
gcodePointer++;
if(gcodePointer >= GCODE_LENGTH)
{
platform->Message(HOST_MESSAGE, "G Code buffer length overflow.<br>\n");
gcodePointer = 0;
gcodeBuffer[0] = 0;
}
return result;
}
// Is 'c' in the G Code string?
// Leave the pointer there for a subsequent read.
boolean GCodeBuffer::Seen(char c)
{
readPointer = 0;
while(gcodeBuffer[readPointer])
{
if(gcodeBuffer[readPointer] == c)
return true;
readPointer++;
}
readPointer = -1;
return false;
}
// Get a float after a G Code letter
float GCodeBuffer::GetFValue()
{
if(readPointer < 0)
{
platform->Message(HOST_MESSAGE, "GCodes: Attempt to read a GCode float before a search.<br>\n");
return 0.0;
}
float result = (float)strtod(&gcodeBuffer[readPointer + 1], NULL);
readPointer = -1;
return result;
}
// Get an Int after a G Code letter
int GCodeBuffer::GetIValue()
{
if(readPointer < 0)
{
platform->Message(HOST_MESSAGE, "GCodes: Attempt to read a GCode int before a search.<br>\n");
return 0;
}
int result = (int)strtol(&gcodeBuffer[readPointer + 1], NULL, 0);
readPointer = -1;
return result;
}
char* GCodeBuffer::Buffer()
{
return gcodeBuffer;
}