/*
Copyright (C) 2012, Tórur Biskopstø Strøm (torur.strom@gmail.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.reprap;
import javax.realtime.PeriodicParameters;
import javax.realtime.PriorityParameters;
import javax.realtime.RelativeTime;
import javax.safetycritical.PeriodicEventHandler;
import javax.safetycritical.StorageParameters;
import org.reprap.commands.*;
public class CommandParser extends PeriodicEventHandler
{
private static final int MAX_NUMBER_LENGTH = 5;
private boolean waiting = false;
private HostController hostController;
private int lineNumber = 0;
private char[] chars = new char[64];
private int length = 0;
private G1Pool G1Pool;
private G28Pool G28Pool;
private G21 G21;
private G90 G90;
private G91 G91;
private G92 G92;
private M82 M82;
private M104 M104;
private M105 M105;
private M109 M109;
private M110 M110;
private M113 M113;
private M140 M140;
private T T;
CommandParser(HostController hostController, CommandController commandController, RepRapController repRapController)
{
super(new PriorityParameters(4),
new PeriodicParameters(null, new RelativeTime(60,0)),
// new StorageParameters(100, new long[]{100}, 0, 0), 0);
new StorageParameters(100, null, 0, 0), 100);
this.hostController = hostController;
G1Pool = new G1Pool(hostController, commandController, repRapController);
G28Pool = new G28Pool(hostController, commandController, repRapController);
G21 = new G21(hostController, commandController);
G90 = new G90(hostController, commandController, repRapController);
G91 = new G91(hostController, commandController, repRapController);
G92 = new G92(hostController, commandController, repRapController);
M82 = new M82(hostController, commandController);
M104 = new M104(hostController, commandController, repRapController);
M105 = new M105(hostController, commandController, repRapController);
M109 = new M109(hostController, commandController, repRapController);
M110 = new M110(hostController, commandController);
M113 = new M113(hostController, commandController);
M140 = new M140(hostController, commandController);
T = new T(hostController, commandController);
this.thread.setProcessor(3);
}
@Override
public void handleAsyncEvent()
{
if(!waiting)
{
length = hostController.getLine(chars);
if(length == 0)
{
return;
}
}
else
{
waiting = false;
}
boolean seenNCommand = false;
int lineNumberN = Integer.MIN_VALUE;
boolean seenGCommand = false;
boolean seenMCommand = false;
boolean seenTCommand = false;
int commandNumber = Integer.MIN_VALUE;
Parameter parameter = new Parameter();
boolean seenStarCommand = false;
int checksum = 0;
for(int i = 0; i < length; i++) //@WCA loop = 64
{
char character = chars[i];
char command = character;
int numberLength = 0;
int value = 0;
boolean decimalpoint = false;
boolean negative = false;
int decimals = 0;
for(int j = i+1; j < length; j++) //@WCA loop = 1
{
character = chars[j];
if(Character.digit(character, 10) > -1)
{
//Ignore the rest of the decimals
if(numberLength < MAX_NUMBER_LENGTH && (!decimalpoint || decimals < RepRapController.NR_DECIMALS))
{
value = value * 10 + character-48;//Numbers start at character position 48
numberLength++;
if(decimalpoint)
{
decimals++;
}
}
}
else if(character == '.' && numberLength > 0)
{
decimalpoint = true;
}
else if(character == '-' && numberLength == 0)
{
negative = true;
}
else
{
//Command delimiter
break;
}
i++;
}
if(numberLength == 0)
{
//All commands should have a number
//hostController.resendCommand(INCORRECT_COMMAND);
continue;
}
if(negative)
{
value = -value;
}
int shiftedValue = value;
for (int j = 0; j < RepRapController.NR_DECIMALS-decimals; j++) //@WCA loop = 1
{
shiftedValue = shiftedValue*10;
}
//Not using switch because of WCET analysis and JOP
if(command == 'N')
{
lineNumberN = value;
seenNCommand = true;
}
else if(command == 'G')
{
commandNumber = value;
seenGCommand = true;
}
else if(command == 'M')
{
commandNumber = value;
seenMCommand = true;
}
else if(command == 'F')
{
parameter.F = shiftedValue;
}
else if(command == 'S')
{
parameter.S = shiftedValue;
}
else if(command == 'T')
{
commandNumber = value;
seenTCommand = true;
}
else if(command == 'X')
{
parameter.X = shiftedValue;
}
else if(command == 'Y')
{
parameter.Y = shiftedValue;
}
else if(command == 'Z')
{
parameter.Z = shiftedValue;
}
else if(command == 'E')
{
parameter.E = shiftedValue;
}
else if(command == '*')
{
checksum = value;
seenStarCommand = true;
}
}
if(seenNCommand && seenStarCommand)
{
if(!verifyChecksum(chars,checksum) || (lineNumberN != -1 && lineNumberN != lineNumber))
{
hostController.resendCommand(lineNumber,chars);
return;
}
}
if(seenGCommand)
{
if(commandNumber == 0 || commandNumber == 1)
{
//Buffered command
if(!G1Pool.enqueue(parameter))
{
waiting = true;
return;
}
hostController.confirmCommand(null);
}
else if(commandNumber == 21)
{
waiting = !G21.enqueue();
}
else if(commandNumber == 28)
{
//Buffered command
if(!G28Pool.enqueue(parameter))
{
waiting = true;
return;
}
hostController.confirmCommand(null);
}
else if(commandNumber == 90)
{
waiting = !G90.enqueue();
}
else if(commandNumber == 91)
{
waiting = !G91.enqueue();
}
else if(commandNumber == 92)
{
waiting = !G92.enqueue(parameter);
}
else
{
hostController.resendCommand(lineNumberN,chars);
return;
}
}
else if(seenMCommand)
{
if(commandNumber == 82)
{
waiting = !M82.enqueue();
}
else if(commandNumber == 104)
{
waiting = !M104.enqueue(parameter.S);
}
else if(commandNumber == 105)
{
waiting = !M105.enqueue();
}
else if(commandNumber == 109)
{
waiting = !M109.enqueue(parameter.S);
}
else if(commandNumber == 110)
{
if(!M110.enqueue())
{
waiting = true;
return;
}
lineNumber = lineNumberN;
}
else if(commandNumber == 113)
{
waiting = !M113.enqueue();
}
else if(commandNumber == 140)
{
waiting = !M140.enqueue();
}
else
{
hostController.resendCommand(lineNumberN,chars);
return;
}
}
else if(seenTCommand)
{
waiting = !T.enqueue();
}
else
{
hostController.resendCommand(lineNumberN,chars);
return;
}
if(waiting)
{
return;
}
if(seenNCommand && seenStarCommand)
{
lineNumber++;
}
}
private static boolean verifyChecksum(char[] chars, int checksum)
{
int calculatedChecksum = 0;
for(int i = 0; i < chars.length && chars[i] != '*'; i++) //@WCA loop = 64
{
calculatedChecksum = calculatedChecksum ^ chars[i];
}
return (calculatedChecksum == checksum);
}
}