Welcome to mirror list, hosted at ThFree Co, Russian Federation.

GCodeBuffer.h « GCodes « src - github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: fb64ff6f2b7714dfd20466ebc50e6a2ab7fb9143 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*
 * GCodeBuffer.h
 *
 *  Created on: 6 Feb 2015
 *      Author: David
 */

#ifndef GCODEBUFFER_H_
#define GCODEBUFFER_H_

#include "RepRapFirmware.h"
#include "GCodeMachineState.h"
#include "MessageType.h"

// Class to hold an individual GCode and provide functions to allow it to be parsed
class GCodeBuffer
{
public:
	GCodeBuffer(const char* id, MessageType mt, bool useCodeQueue);
	void Reset();										// Reset it to its state after start-up
	void Init(); 										// Set it up to parse another G-code
	void Diagnostics(MessageType mtype);				// Write some debug info
	bool Put(char c) __attribute__((hot));				// Add a character to the end
	void Put(const char *str, size_t len);				// Add an entire string, overwriting any existing content
	void Put(const char *str);							// Add a null-terminated string, overwriting any existing content
	bool Seen(char c) __attribute__((hot));				// Is a character present?

	char GetCommandLetter() const { return commandLetter; }
	bool HasCommandNumber() const { return hasCommandNumber; }
	int GetCommandNumber() const { return commandNumber; }
	int8_t GetCommandFraction() const { return commandFraction; }

	float GetFValue() __attribute__((hot));				// Get a float after a key letter
	int32_t GetIValue() __attribute__((hot));			// Get an integer after a key letter
	uint32_t GetUIValue();								// Get an unsigned integer value
	bool GetIPAddress(uint8_t ip[4]);					// Get an IP address quad after a key letter
	bool GetIPAddress(uint32_t& ip);					// Get an IP address quad after a key letter
	bool GetMacAddress(uint8_t mac[6]);					// Get a MAX address sextet after a key letter
	bool GetUnprecedentedString(const StringRef& str);	// Get a string with no preceding key letter
	bool GetQuotedString(const StringRef& str);			// Get and copy a quoted string
	bool GetPossiblyQuotedString(const StringRef& str);	// Get and copy a string which may or may not be quoted
	const void GetFloatArray(float arr[], size_t& length, bool doPad) __attribute__((hot)); // Get a :-separated list of floats after a key letter
	const void GetIntArray(int32_t arr[], size_t& length, bool doPad);			// Get a :-separated list of ints after a key letter
	const void GetUnsignedArray(uint32_t arr[], size_t& length, bool doPad);	// Get a :-separated list of unsigned ints after a key letter

	void TryGetFValue(char c, float& val, bool& seen);
	void TryGetIValue(char c, int32_t& val, bool& seen);
	void TryGetUIValue(char c, uint32_t& val, bool& seen);
	bool TryGetFloatArray(char c, size_t numVals, float vals[], const StringRef& reply, bool& seen, bool doPad = false);
	bool TryGetQuotedString(char c, const StringRef& str, bool& seen);
	bool TryGetPossiblyQuotedString(char c, const StringRef& str, bool& seen);

	const char* Buffer() const;
	bool IsIdle() const;
	bool IsCompletelyIdle() const;
	bool IsReady() const;								// Return true if a gcode is ready but hasn't been started yet
	bool IsExecuting() const;							// Return true if a gcode has been started and is not paused
	void SetFinished(bool f);							// Set the G Code executed (or not)
	const char* WritingFileDirectory() const;			// If we are writing the G Code to a file, where that file is
	void SetWritingFileDirectory(const char* wfd);		// Set the directory for the file to write the GCode in
	int GetToolNumberAdjust() const { return toolNumberAdjust; }
	void SetToolNumberAdjust(int arg) { toolNumberAdjust = arg; }
	void SetCommsProperties(uint32_t arg) { checksumRequired = (arg & 1); }
	bool StartingNewCode() const { return gcodeLineEnd == 0; }
	MessageType GetResponseMessageType() const { return responseMessageType; }
	GCodeMachineState& MachineState() const { return *machineState; }
	GCodeMachineState& OriginalMachineState() const;
	bool PushState();									// Push state returning true if successful (i.e. stack not overflowed)
	bool PopState();									// Pop state returning true if successful (i.e. no stack underrun)
	void AbortFile();									// Abort execution of any files or macros being executed

	bool IsDoingFileMacro() const;						// Return true if this source is executing a file macro
	GCodeState GetState() const;
	void SetState(GCodeState newState);
	void SetState(GCodeState newState, const char *err);
	void AdvanceState();
	const char *GetIdentity() const { return identity; }
	bool CanQueueCodes() const;
	void MessageAcknowledged(bool cancelled);
	FilePosition GetFilePosition(size_t bytesCached) const;	// Get the file position at the start of the current command
	bool IsWritingBinary() const;						// returns true if writing binary
	void SetBinaryWriting(bool state);					// set true if writing binary
	uint32_t GetCRC32() const;
	void SetCRC32(uint32_t newCRC32);

	void PrintCommand(const StringRef& s) const;

	uint32_t whenTimerStarted;							// when we started waiting
	bool timerRunning;									// true if we are waiting

private:

	enum class GCodeBufferState : uint8_t
	{
		parseNotStarted,								// we haven't started parsing yet
		parsingLineNumber,								// we saw N at the start and we are parsing the line number
		parsingWhitespace,								// parsing whitespace after the line number
		parsingGCode,									// parsing GCode words
		parsingBracketedComment,						// inside a (...) comment
		parsingQuotedString,							// inside a double-quoted string
		parsingChecksum,								// parsing the checksum after '*'
		discarding,										// discarding characters after the checksum or an end-of-line comment
		ready,											// we have a complete gcode but haven't started executing it
		executing										// we have a complete gcode and have started executing it
	};

	void AddToChecksum(char c);
	void StoreAndAddToChecksum(char c);
	bool LineFinished();								// Deal with receiving end-of-line and return true if we have a command
	void DecodeCommand();
	bool InternalGetQuotedString(const StringRef& str)
		pre (gcodeBuffer[readPointer] == '"'; str.IsEmpty());
	bool InternalGetPossiblyQuotedString(const StringRef& str)
		pre (readPointer >= 0);

	GCodeMachineState *machineState;					// Machine state for this gcode source
	char gcodeBuffer[GCODE_LENGTH];						// The G Code
	const char* const identity;							// Where we are from (web, file, serial line etc)
	unsigned int commandStart;							// Index in the buffer of the command letter of this command
	unsigned int parameterStart;
	unsigned int commandEnd;							// Index in the buffer of one past the last character of this command
	unsigned int commandLength;							// Number of characters we read to build this command including the final \r or \n
	unsigned int gcodeLineEnd;							// Number of characters in the entire line of gcode
	int readPointer;									// Where in the buffer to read next
	bool checksumRequired;								// True if we only accept commands with a valid checksum
	GCodeBufferState bufferState;						// Idle, executing or paused
	const char* writingFileDirectory;					// If the G Code is going into a file, where that is
	int toolNumberAdjust;								// The adjustment to tool numbers in commands we receive
	const MessageType responseMessageType;				// The message type we use for responses to commands coming from this channel
	unsigned int lineNumber;
	unsigned int declaredChecksum;
	uint8_t computedChecksum;
	bool hadLineNumber;
	bool hadChecksum;
	bool hasCommandNumber;
	char commandLetter;
	int commandNumber;
	int8_t commandFraction;

	bool queueCodes;									// Can we queue certain G-codes from this source?
	bool binaryWriting;									// Executing gcode or writing binary file?
	uint32_t crc32;										// crc32 of the binary file
};

inline uint32_t GCodeBuffer::GetCRC32() const
{
	return crc32;
}

inline void GCodeBuffer::SetCRC32(uint32_t newCRC32)
{
	crc32 = newCRC32;
}

inline bool GCodeBuffer::IsWritingBinary() const
{
	return binaryWriting;
}

inline void GCodeBuffer::SetBinaryWriting(bool state)
{
	binaryWriting = state;
}

inline const char* GCodeBuffer::Buffer() const
{
	return gcodeBuffer;
}

inline bool GCodeBuffer::IsIdle() const
{
	return bufferState != GCodeBufferState::ready && bufferState != GCodeBufferState::executing;
}

inline bool GCodeBuffer::IsCompletelyIdle() const
{
	return GetState() == GCodeState::normal && IsIdle();
}

inline bool GCodeBuffer::IsReady() const
{
	return bufferState == GCodeBufferState::ready;
}

inline bool GCodeBuffer::IsExecuting() const
{
	return bufferState == GCodeBufferState::executing;
}

inline const char* GCodeBuffer::WritingFileDirectory() const
{
	return writingFileDirectory;
}

inline void GCodeBuffer::SetWritingFileDirectory(const char* wfd)
{
	writingFileDirectory = wfd;
}

inline GCodeState GCodeBuffer::GetState() const
{
	return machineState->state;
}

inline void GCodeBuffer::SetState(GCodeState newState)
{
	machineState->state = newState;
}

inline void GCodeBuffer::SetState(GCodeState newState, const char *err)
{
	machineState->state = newState;
	machineState->err = err;
}

inline void GCodeBuffer::AdvanceState()
{
	machineState->state = static_cast<GCodeState>(static_cast<uint8_t>(machineState->state) + 1);
}

#endif /* GCODEBUFFER_H_ */