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