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

GCodes7.cpp « GCodes « src - github.com/Duet3D/RepRapFirmware.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 23abce061db8f251478fdaee2621dc29f840dcf5 (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
/*
 * GCodes7.cpp
 *
 *  Created on: 14 Sept 2022
 *      Author: David
 *
 *  This file handles M291, M292 and other functions related to message boxes
 */

#include "GCodes.h"
#include "GCodeBuffer/GCodeBuffer.h"

// Process M291
GCodeResult GCodes::DoMessageBox(GCodeBuffer&gb, const StringRef& reply) THROWS(GCodeException)
{
	// Get the message
	gb.MustSee('P');
	String<MaxMessageLength> message;
	gb.GetQuotedString(message.GetRef());

	// Get the optional message box title
	bool dummy = false;
	String<StringLength100> title;
	(void)gb.TryGetQuotedString('R', title.GetRef(), dummy);

	// Get the message box mode
	uint32_t sParam = 1;
	(void)gb.TryGetLimitedUIValue('S', sParam, dummy, 8);

	// Get the optional timeout parameter. The default value depends on the mode (S parameter).
	float tParam = (sParam <= 1) ? DefaultMessageTimeout : 0.0;
	gb.TryGetNonNegativeFValue('T', tParam, dummy);

	MessageBoxLimits limits;
	gb.TryGetBValue('J', limits.canCancel, dummy);

	AxesBitmap axisControls;

	switch (sParam)
	{
	case 0:		// no buttons displayed, non-blocking
		if (tParam <= 0.0)
		{
			reply.copy("Attempt to create a message box that cannot be dismissed");
			return GCodeResult::error;
		}
		break;

	case 1:		// Close button displayed, non-blocking
	default:
		break;

	case 2:		// OK button displayed, blocking
	case 3:		// OK and Cancel buttons displayed, blocking
		// Message box modes 2 and 3 can take a list of axes that can be jogged
		for (size_t axis = 0; axis < numTotalAxes; axis++)
		{
			if (gb.Seen(axisLetters[axis]) && gb.GetIValue() > 0)
			{
				axisControls.SetBit(axis);
			}
		}
		break;

	case 4:		// Multiple choices, blocking
		gb.MustSee('K');
		limits.choices = gb.GetExpression();
		if (limits.choices.IsHeapStringArrayType())
		{
			uint32_t defaultChoice = 0;
			if (gb.TryGetUIValue('F', defaultChoice, dummy))
			{
				limits.defaultVal.SetInt((int32_t)defaultChoice);
			}
			break;
		}
		reply.copy("K parameter must be an array of strings");
		return GCodeResult::error;

	case 5:		// Integer value required, blocking
		limits.GetIntegerLimits(gb, false);
		break;

	case 6:		// Floating point value required, blocking
		limits.GetFloatLimits(gb);
		break;

	case 7:		// String value required, blocking
		limits.GetIntegerLimits(gb, true);
		break;
	}

	if (sParam >= 2)			// if it's a blocking message box
	{
		// Don't lock the movement system, because if we do then only the channel that issues the M291 can move the axes
#if HAS_SBC_INTERFACE
		if (reprap.UsingSbcInterface())
		{
			gb.SetState(GCodeState::waitingForAcknowledgement);
		}
#endif
		if (Push(gb, true))												// stack the machine state including the file position
		{
			UnlockMovement(gb);											// allow movement so that e.g. an SD card print can call M291 and then DWC or PanelDue can be used to jog axes
			gb.WaitForAcknowledgement();								// flag that we are waiting for acknowledgement
		}
	}

	// Display the message box on all relevant devices. Acknowledging any one of them clears them all.
	const MessageType mt = GetMessageBoxDevice(gb);						// get the display device
	reprap.SendAlert(mt, message.c_str(), title.c_str(), (int)sParam, tParam, axisControls, &limits);
	return GCodeResult::ok;
}

// Process M292
GCodeResult GCodes::AcknowledgeMessage(GCodeBuffer&gb, const StringRef& reply) THROWS(GCodeException)
{
	uint32_t seq = 0;
	if (gb.Seen('S'))
	{
		seq = gb.GetUIValue();
	}

	bool wasBlocking;
	if (reprap.AcknowledgeMessageBox(seq, wasBlocking))
	{
		if (wasBlocking)
		{
			const bool cancelled = (gb.Seen('P') && gb.GetIValue() == 1);
			ExpressionValue rslt;
			if (!cancelled && gb.Seen('R'))
			{
				rslt = gb.GetExpression();
			}
			MessageBoxClosed(cancelled, true, rslt);
		}
		return GCodeResult::ok;
	}
	else
	{
		reply.copy("no active message box");
		return GCodeResult::error;
	}
}

// Deal with processing a M292 or timing out a message box
void GCodes::MessageBoxClosed(bool cancelled, bool m292, ExpressionValue rslt) noexcept
{
	platform.MessageF(MessageType::LogInfo,
						"%s: cancelled=%s",
							(m292) ? "M292" : "Message box timed out",
								(cancelled ? "true" : "false"));
	for (GCodeBuffer* targetGb : gcodeSources)
	{
		if (targetGb != nullptr)
		{
			targetGb->MessageAcknowledged(cancelled, rslt);
		}
	}
}

// End