PageRenderTime 37ms CodeModel.GetById 18ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/firmware/tests/T5-Extruder/src/T5-Extruder-exerciser.cc

http://github.com/makerbot/G3Firmware
C++ | 293 lines | 200 code | 32 blank | 61 comment | 17 complexity | 97427ef405d228317134a09d76def543 MD5 | raw file
  1/*
  2 * T1-UART-exerciser.cc
  3 *
  4 *  Created on: Dec 10, 2009
  5 *      Author: phooky
  6 */
  7
  8/// Based on the hoary old serial-programming HOWTO
  9
 10#include <termios.h>
 11#include <stdio.h>
 12#include <unistd.h>
 13#include <fcntl.h>
 14#include <sys/signal.h>
 15#include <sys/types.h>
 16#include <stdlib.h>
 17#include <getopt.h>
 18#include <sys/time.h>
 19#include <gtest/gtest.h>
 20#include <math.h>
 21
 22#include <vector>
 23
 24#include "Packet.hh"
 25#include "Commands.hh"
 26
 27using namespace std;
 28
 29#define COMMAND_BUFFER_SIZE 256
 30
 31const char* default_port = "/dev/ttyUSB0";
 32#define BAUDRATE B38400
 33#define _POSIX_SOURCE 1 /* POSIX compliant source */
 34
 35class SerialTest: public ::testing::Test {
 36protected:
 37	const char* port_name_;
 38	int serial_fd_;
 39	struct termios oldtio_;
 40	InPacket in_;
 41	OutPacket out_;
 42	uint16_t sequence_number_;
 43public:
 44	SerialTest() :
 45		sequence_number_(0) {
 46	}
 47	void SetUp() {
 48		port_name_ = getenv("PORT");
 49		if (port_name_ == NULL) {
 50			port_name_ = default_port;
 51		}
 52		struct termios newtio;
 53		char buf[255];
 54
 55		/* open the device to be non-blocking (read will return immediately) */
 56		serial_fd_ = open(port_name_, O_RDWR | O_NOCTTY | O_NONBLOCK);
 57		if (serial_fd_ < 0) {
 58			perror(port_name_);
 59			return;
 60		}
 61
 62		tcgetattr(serial_fd_, &oldtio_); /* save current port settings */
 63		/* set new port settings for canonical input processing */
 64		newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
 65
 66		newtio.c_cflag &= ~PARENB;
 67		newtio.c_cflag &= ~CSTOPB;
 68		newtio.c_cflag &= ~CSIZE;
 69		newtio.c_cflag |= CS8;
 70
 71		newtio.c_iflag = IGNPAR;
 72		newtio.c_oflag = 0;
 73		newtio.c_lflag = 0;
 74		newtio.c_cc[VMIN] = 1;
 75		newtio.c_cc[VTIME] = 0;
 76		tcflush(serial_fd_, TCIFLUSH);
 77		tcsetattr(serial_fd_, TCSANOW, &newtio);
 78	}
 79	void TearDown() {
 80		/* restore old port settings */
 81		tcsetattr(serial_fd_, TCSANOW, &oldtio_);
 82		close(serial_fd_);
 83	}
 84
 85	void makeToolQuery(uint8_t code, vector<uint8_t>& payload);
 86	void makeToolCommand(uint8_t code, vector<uint8_t>& payload);
 87
 88	void writePacket();
 89	void readPacketWithTimeout(uint16_t timeout);
 90
 91	void runPacket();
 92	void runCommandPacket();
 93	void reset();
 94
 95	void setTemperature(uint16_t celsius);
 96	uint16_t getTemperature();
 97	void waitForTool();
 98};
 99
100void SerialTest::makeToolQuery(uint8_t code, vector<uint8_t>& payload) {
101	reset();
102	out_.append8(HOST_CMD_TOOL_QUERY);
103	out_.append8(0);
104	out_.append8(code);
105	for (int i = 0; i < payload.size(); i++) {
106		out_.append8(payload[i]);
107	}
108}
109
110void SerialTest::makeToolCommand(uint8_t code, vector<uint8_t>& payload) {
111	reset();
112	out_.append8(HOST_CMD_TOOL_COMMAND);
113	out_.append8(0);
114	out_.append8(code);
115	out_.append8(payload.size());
116	for (int i = 0; i < payload.size(); i++) {
117		out_.append8(payload[i]);
118	}
119}
120
121uint16_t SerialTest::getTemperature() {
122	vector<uint8_t> payload;
123	makeToolQuery(SLAVE_CMD_GET_TEMP,payload);
124	runPacket();
125	EXPECT_EQ(3,in_.getLength());
126	return in_.read16(1);
127}
128
129void SerialTest::setTemperature(uint16_t celsius) {
130	vector<uint8_t> payload;
131	payload.push_back(celsius&0xff);
132	payload.push_back((celsius>>8)&0xff);
133	makeToolCommand(SLAVE_CMD_SET_TEMP,payload);
134	runCommandPacket();
135}
136
137const char* port_string = default_port;
138
139class Timer {
140private:
141	struct timeval start_;
142public:
143	Timer() {
144		gettimeofday(&start_, NULL);
145	}
146	long millisSince() {
147		struct timeval now;
148		gettimeofday(&now, NULL);
149		return ((now.tv_sec - start_.tv_sec) * 1000L) + (now.tv_usec
150				- start_.tv_usec) / 1000L;
151	}
152};
153
154void SerialTest::writePacket() {
155	while (!out_.isFinished()) {
156		uint8_t out_byte = out_.getNextByteToSend();
157		write(serial_fd_, &out_byte, 1);
158	}
159}
160
161void SerialTest::readPacketWithTimeout(uint16_t timeout) {
162	Timer mark;
163	while (!in_.isFinished()) {
164		if (mark.millisSince() > timeout) {
165			in_.timeout();
166			printf("state is %d\n",in_.debugGetState());
167			break;
168		}
169		uint8_t in_byte;
170		int count = read(serial_fd_, &in_byte, 1);
171		if (count == 1) {
172			in_.processByte(in_byte);
173		}
174	}
175}
176
177void SerialTest::runPacket() {
178	writePacket();
179	readPacketWithTimeout(50);
180	ASSERT_TRUE(in_.isFinished());
181	ASSERT_FALSE(in_.hasError());
182	ASSERT_EQ(in_.read8(0), RC_OK);
183}
184
185void SerialTest::runCommandPacket() {
186	bool done = false;
187	while (!done) {
188		writePacket();
189		readPacketWithTimeout(50);
190		ASSERT_TRUE(in_.isFinished());
191		ASSERT_FALSE(in_.hasError());
192		ASSERT_EQ(in_.read8(0), RC_OK);
193		if (in_.read8(0)== RC_OK) {
194			done=true;
195		} else {
196			ASSERT_EQ(in_.read8(0),RC_BUFFER_OVERFLOW);
197			// delay for 1ms
198			struct timespec t;
199			t.tv_sec = 0;
200			t.tv_nsec = 10 * 1000 * 1000;
201			nanosleep(&t,NULL);
202		}
203	}
204}
205
206void SerialTest::reset() {
207	in_.reset();
208	out_.reset();
209}
210
211TEST_F(SerialTest,CheckTemperature)
212{
213	uint16_t temp = getTemperature();
214	ASSERT_GE(temp,5);
215	ASSERT_LT(temp,250);
216	cout << "Temperature: " << temp << endl;
217}
218
219TEST_F(SerialTest,SetTemperature)
220{
221	setTemperature(0);
222	uint16_t start_temp = getTemperature();
223	while (start_temp > 90) {
224		cout << "Cooldown in progress." << endl;
225		sleep(3);
226		start_temp = getTemperature();
227	}
228	cout << "Temperature at start: " << start_temp << endl;
229	bool done = false;
230	setTemperature(120);
231	int waited = 0;
232	while (!done) {
233		sleep(3); waited += 3;
234		uint16_t temp = getTemperature();
235		cout << "Temperature: " << temp << endl;
236		if (waited > 20) ASSERT_GE(temp,start_temp);
237		if (temp > 120) done = true;
238	}
239	setTemperature(0);
240}
241
242
243/*
244TEST_F(SerialTest,Init)
245{
246	reset();
247	out_.append8(HOST_CMD_INIT);
248	runPacket();
249	/// No response
250}
251
252TEST_F(SerialTest,IsFinished)
253{
254	SCOPED_TRACE("Initial finished");
255	reset();
256	out_.append8(HOST_CMD_IS_FINISHED);
257	runPacket();
258	/// Should respond with a 1 (yes, we're done)
259	ASSERT_EQ(in_.read8(1), 1);
260	/// Start a move
261	SCOPED_TRACE("Adding moves");
262	resetPosition();
263	moveTo(500,500,0,500);
264	moveTo(0,0,0,500);
265	/// Should be busy
266	reset();
267	out_.append8(HOST_CMD_IS_FINISHED);
268	runPacket();
269	/// Should respond with a 0 (no, not done)
270	ASSERT_EQ(in_.read8(1), 0);
271	/// Wait until done
272	bool done = false;
273	while (!done) {
274		reset();
275		out_.append8(HOST_CMD_IS_FINISHED);
276		runPacket();
277		done = in_.read8(1) == 1;
278	}
279}
280*/
281/*
282/// Wait until done
283void SerialTest::waitUntilDone() {
284	bool done = false;
285	while (!done) {
286		reset();
287		out_.append8(HOST_CMD_IS_FINISHED);
288		runPacket();
289		done = in_.read8(1) == 1;
290	}
291}
292*/
293