/firmware/tests/T4-Commands/src/T4-Commands-exerciser.cc

http://github.com/makerbot/G3Firmware · C++ · 418 lines · 308 code · 40 blank · 70 comment · 23 complexity · e863e4159eed6f38851d1cc597f72f12 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 "Packet.hh"
  20. #include "Commands.hh"
  21. #define COMMAND_BUFFER_SIZE 256
  22. const char* default_port = "/dev/ttyUSB0";
  23. #define BAUDRATE B38400
  24. #define _POSIX_SOURCE 1 /* POSIX compliant source */
  25. class SerialTest: public ::testing::Test {
  26. protected:
  27. const char* port_name_;
  28. int serial_fd_;
  29. struct termios oldtio_;
  30. InPacket in_;
  31. OutPacket out_;
  32. uint16_t sequence_number_;
  33. public:
  34. SerialTest() :
  35. sequence_number_(0) {
  36. }
  37. void SetUp() {
  38. port_name_ = getenv("PORT");
  39. if (port_name_ == NULL) {
  40. port_name_ = default_port;
  41. }
  42. struct termios newtio;
  43. char buf[255];
  44. /* open the device to be non-blocking (read will return immediately) */
  45. serial_fd_ = open(port_name_, O_RDWR | O_NOCTTY | O_NONBLOCK);
  46. if (serial_fd_ < 0) {
  47. perror(port_name_);
  48. return;
  49. }
  50. tcgetattr(serial_fd_, &oldtio_); /* save current port settings */
  51. /* set new port settings for canonical input processing */
  52. newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
  53. newtio.c_cflag &= ~PARENB;
  54. newtio.c_cflag &= ~CSTOPB;
  55. newtio.c_cflag &= ~CSIZE;
  56. newtio.c_cflag |= CS8;
  57. newtio.c_iflag = IGNPAR;
  58. newtio.c_oflag = 0;
  59. newtio.c_lflag = 0;
  60. newtio.c_cc[VMIN] = 1;
  61. newtio.c_cc[VTIME] = 0;
  62. tcflush(serial_fd_, TCIFLUSH);
  63. tcsetattr(serial_fd_, TCSANOW, &newtio);
  64. }
  65. void TearDown() {
  66. /* restore old port settings */
  67. tcsetattr(serial_fd_, TCSANOW, &oldtio_);
  68. close(serial_fd_);
  69. }
  70. void writePacket();
  71. void readPacketWithTimeout(uint16_t timeout);
  72. void runPacket();
  73. void reset();
  74. void resetPosition();
  75. void moveTo(int x, int y, int z, int dda);
  76. void delay(float seconds);
  77. void waitUntilDone();
  78. };
  79. void SerialTest::moveTo(int x, int y, int z, int dda) {
  80. bool done = false;
  81. while (!done) {
  82. reset();
  83. out_.append8(HOST_CMD_QUEUE_POINT_ABS);
  84. out_.append32(x);
  85. out_.append32(y);
  86. out_.append32(z);
  87. out_.append32(dda);
  88. writePacket();
  89. readPacketWithTimeout(50);
  90. ASSERT_TRUE(in_.isFinished());
  91. ASSERT_FALSE(in_.hasError());
  92. if (in_.read8(0)== RC_OK) {
  93. done=true;
  94. } else {
  95. ASSERT_EQ(in_.read8(0),RC_BUFFER_OVERFLOW);
  96. // delay for 1ms
  97. struct timespec t;
  98. t.tv_sec = 0;
  99. t.tv_nsec = 10 * 1000 * 1000;
  100. nanosleep(&t,NULL);
  101. }
  102. }
  103. }
  104. void SerialTest::delay(float seconds) {
  105. bool done = false;
  106. int32_t milliseconds = (int32_t) (seconds * 1000.0);
  107. while (!done) {
  108. reset();
  109. out_.append8(HOST_CMD_DELAY);
  110. out_.append32(milliseconds);
  111. writePacket();
  112. readPacketWithTimeout(50);
  113. ASSERT_TRUE(in_.isFinished());
  114. ASSERT_FALSE(in_.hasError());
  115. if (in_.read8(0)== RC_OK) {
  116. done=true;
  117. } else {
  118. ASSERT_EQ(in_.read8(0),RC_BUFFER_OVERFLOW);
  119. // delay for 1ms
  120. struct timespec t;
  121. t.tv_sec = 0;
  122. t.tv_nsec = 10 * 1000 * 1000;
  123. nanosleep(&t,NULL);
  124. }
  125. }
  126. }
  127. void SerialTest::resetPosition() {
  128. reset();
  129. out_.append8(HOST_CMD_SET_POSITION);
  130. out_.append32(0);
  131. out_.append32(0);
  132. out_.append32(0);
  133. runPacket();
  134. }
  135. const char* port_string = default_port;
  136. class Timer {
  137. private:
  138. struct timeval start_;
  139. public:
  140. Timer() {
  141. gettimeofday(&start_, NULL);
  142. }
  143. long millisSince() {
  144. struct timeval now;
  145. gettimeofday(&now, NULL);
  146. return ((now.tv_sec - start_.tv_sec) * 1000L) + (now.tv_usec
  147. - start_.tv_usec) / 1000L;
  148. }
  149. };
  150. void SerialTest::writePacket() {
  151. while (!out_.isFinished()) {
  152. uint8_t out_byte = out_.getNextByteToSend();
  153. write(serial_fd_, &out_byte, 1);
  154. }
  155. }
  156. void SerialTest::readPacketWithTimeout(uint16_t timeout) {
  157. Timer mark;
  158. while (!in_.isFinished()) {
  159. if (mark.millisSince() > timeout) {
  160. in_.timeout();
  161. printf("state is %d\n",in_.debugGetState());
  162. break;
  163. }
  164. uint8_t in_byte;
  165. int count = read(serial_fd_, &in_byte, 1);
  166. if (count == 1) {
  167. in_.processByte(in_byte);
  168. }
  169. }
  170. }
  171. void SerialTest::runPacket() {
  172. writePacket();
  173. readPacketWithTimeout(50);
  174. ASSERT_TRUE(in_.isFinished());
  175. ASSERT_FALSE(in_.hasError());
  176. ASSERT_EQ(in_.read8(0), RC_OK);
  177. }
  178. void SerialTest::reset() {
  179. in_.reset();
  180. out_.reset();
  181. }
  182. TEST_F(SerialTest,CheckVersion)
  183. {
  184. reset();
  185. out_.append8(HOST_CMD_VERSION);
  186. runPacket();
  187. /// Version should be >=200, <300
  188. ASSERT_GE(in_.read8(1), 200);
  189. ASSERT_LT(in_.read8(1), 300);
  190. }
  191. /*
  192. TEST_F(SerialTest,Init)
  193. {
  194. reset();
  195. out_.append8(HOST_CMD_INIT);
  196. runPacket();
  197. /// No response
  198. }
  199. TEST_F(SerialTest,IsFinished)
  200. {
  201. SCOPED_TRACE("Initial finished");
  202. reset();
  203. out_.append8(HOST_CMD_IS_FINISHED);
  204. runPacket();
  205. /// Should respond with a 1 (yes, we're done)
  206. ASSERT_EQ(in_.read8(1), 1);
  207. /// Start a move
  208. SCOPED_TRACE("Adding moves");
  209. resetPosition();
  210. moveTo(500,500,0,500);
  211. moveTo(0,0,0,500);
  212. /// Should be busy
  213. reset();
  214. out_.append8(HOST_CMD_IS_FINISHED);
  215. runPacket();
  216. /// Should respond with a 0 (no, not done)
  217. ASSERT_EQ(in_.read8(1), 0);
  218. /// Wait until done
  219. bool done = false;
  220. while (!done) {
  221. reset();
  222. out_.append8(HOST_CMD_IS_FINISHED);
  223. runPacket();
  224. done = in_.read8(1) == 1;
  225. }
  226. }
  227. */
  228. /// Wait until done
  229. void SerialTest::waitUntilDone() {
  230. bool done = false;
  231. while (!done) {
  232. reset();
  233. out_.append8(HOST_CMD_IS_FINISHED);
  234. runPacket();
  235. done = in_.read8(1) == 1;
  236. }
  237. }
  238. TEST_F(SerialTest,Abort)
  239. {
  240. reset();
  241. out_.append8(HOST_CMD_IS_FINISHED);
  242. runPacket();
  243. /// Should respond with a 1 (yes, we're done)
  244. ASSERT_EQ(in_.read8(1), 1);
  245. /// Start a move
  246. resetPosition();
  247. moveTo(500,500,0,2000);
  248. moveTo(500,0,0,2000);
  249. /// Should be busy
  250. reset();
  251. out_.append8(HOST_CMD_IS_FINISHED);
  252. runPacket();
  253. /// Should respond with a 0 (no, not done)
  254. ASSERT_EQ(in_.read8(1), 0);
  255. /// Abort moves
  256. //sleep(1);
  257. reset();
  258. out_.append8(HOST_CMD_ABORT);
  259. runPacket();
  260. reset();
  261. out_.append8(HOST_CMD_IS_FINISHED);
  262. runPacket();
  263. /// Should respond with a 1 (yes, we're done)
  264. ASSERT_EQ(in_.read8(1), 1);
  265. /// Return to zero point
  266. moveTo(0,0,0,2000);
  267. waitUntilDone();
  268. }
  269. TEST_F(SerialTest,NoSuchCommand)
  270. {
  271. reset();
  272. out_.append8(0x75);
  273. writePacket();
  274. readPacketWithTimeout(50);
  275. ASSERT_TRUE(in_.isFinished());
  276. ASSERT_FALSE(in_.hasError());
  277. ASSERT_EQ(in_.read8(0), RC_CMD_UNSUPPORTED);
  278. }
  279. TEST_F(SerialTest,PauseUnpause)
  280. {
  281. reset();
  282. waitUntilDone();
  283. reset();
  284. /// Start a move
  285. resetPosition();
  286. moveTo(0, 750, 0, 1000);
  287. moveTo(0, 0, 0, 1000);
  288. /// Pause after 1s
  289. sleep(1);
  290. reset();
  291. out_.append8(HOST_CMD_PAUSE);
  292. runPacket();
  293. /// Wait 1s, unpause
  294. sleep(1);
  295. reset();
  296. out_.append8(HOST_CMD_PAUSE);
  297. runPacket();
  298. waitUntilDone();
  299. }
  300. TEST_F(SerialTest,Delay)
  301. {
  302. reset();
  303. waitUntilDone();
  304. reset();
  305. /// Start a move
  306. resetPosition();
  307. moveTo(500, 0, 0, 1000);
  308. delay(1.5); // delay for 1.5 seconds
  309. moveTo(0, 0, 0, 1000);
  310. waitUntilDone();
  311. }
  312. TEST_F(SerialTest,Circle)
  313. {
  314. reset();
  315. waitUntilDone();
  316. reset();
  317. /// Start a move
  318. resetPosition();
  319. const float radius = 400.0;
  320. const int speed = 700;
  321. moveTo(0, radius, 0, speed);
  322. for (int i = 0; i < 400; i++) {
  323. double theta = i * M_PI / 50.0;
  324. moveTo(radius*sin(theta), radius*cos(theta),0,speed);
  325. }
  326. moveTo(0,0,0,speed);
  327. waitUntilDone();
  328. }
  329. TEST_F(SerialTest,Eeprom)
  330. {
  331. // write 0 1 2 3 4 5 6
  332. const int pattern_len = 7;
  333. reset();
  334. out_.append8(HOST_CMD_WRITE_EEPROM);
  335. out_.append16(10);
  336. out_.append8(pattern_len);
  337. for (int i = 0; i < pattern_len; i++) {
  338. out_.append8(i);
  339. }
  340. runPacket();
  341. // read back and check
  342. reset();
  343. out_.append8(HOST_CMD_READ_EEPROM);
  344. out_.append16(10);
  345. out_.append8(pattern_len);
  346. runPacket();
  347. for (int i = 0; i < pattern_len; i++) {
  348. ASSERT_EQ(in_.read8(i+1), i);
  349. }
  350. // replace 2nd value with 0xff
  351. reset();
  352. out_.append8(HOST_CMD_WRITE_EEPROM);
  353. out_.append16(12);
  354. out_.append8(1);
  355. out_.append8(0xff);
  356. runPacket();
  357. // read back and check
  358. reset();
  359. out_.append8(HOST_CMD_READ_EEPROM);
  360. out_.append16(10);
  361. out_.append8(pattern_len);
  362. runPacket();
  363. for (int i = 0; i < pattern_len; i++) {
  364. if ( i != 2 ) {
  365. ASSERT_EQ(in_.read8(i+1), i);
  366. } else {
  367. ASSERT_EQ(in_.read8(i+1), 255);
  368. }
  369. }
  370. }
  371. TEST_F(SerialTest,Reset)
  372. {
  373. // Reset device
  374. reset();
  375. out_.append8(HOST_CMD_RESET);
  376. runPacket();
  377. }