machine_interface.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. #ifndef MACHINE_INTERFACE_H_
  2. #define MACHINE_INTERFACE_H_
  3. /*** The CNC-machine interface ***/
  4. #include <stdint.h>
  5. #undef __packed
  6. #define __packed __attribute__((__packed__))
  7. /* Fixed point arithmetics */
  8. typedef int32_t fixpt_t;
  9. #define FIXPT_FRAC_BITS 16
  10. #define FIXPT_FRAC_MASK (((uint32_t)1 << FIXPT_FRAC_BITS) - 1)
  11. #define FIXPT_INT_PART(val) (((int32_t)(val) >> FIXPT_FRAC_BITS) + (fixpt_is_neg(val) ? 1 : 0))
  12. #define FIXPT_FRAC_PART(val) ((uint32_t)fixpt_abs(val) & FIXPT_FRAC_MASK)
  13. #define TO_FIXPT(val) ((fixpt_t)(int32_t)(val))
  14. /* Fixed point arithmetics conversion helpers */
  15. #define FLOAT_TO_FIXPT(f) TO_FIXPT(((float)(f)) * (FIXPT_FRAC_MASK + 1) + 1)
  16. #define INT32_TO_FIXPT(i) TO_FIXPT(((uint32_t)(int32_t)(i)) << FIXPT_FRAC_BITS)
  17. #define fixpt_add(val0, val1) ((fixpt_t)((int32_t)(val0) + (int32_t)(val1)))
  18. #define fixpt_sub(val0, val1) ((fixpt_t)((int32_t)(val0) - (int32_t)(val1)))
  19. #define fixpt_is_neg(val) ((int32_t)(val) < 0)
  20. #define fixpt_neg(val) ((fixpt_t)(-((int32_t)(val))))
  21. static inline fixpt_t fixpt_abs(fixpt_t val)
  22. {
  23. if (fixpt_is_neg(val))
  24. return fixpt_neg(val);
  25. return val;
  26. }
  27. static inline fixpt_t fixpt_mult(fixpt_t val0, fixpt_t val1)
  28. {
  29. int64_t tmp;
  30. tmp = (int64_t)val0 * (int64_t)val1;
  31. tmp += (1ll << (FIXPT_FRAC_BITS - 1));
  32. tmp >>= FIXPT_FRAC_BITS;
  33. return (fixpt_t)(int32_t)tmp;
  34. }
  35. static inline fixpt_t fixpt_div(fixpt_t val0, fixpt_t val1)
  36. {
  37. int64_t tmp;
  38. tmp = (int64_t)val0 << FIXPT_FRAC_BITS;
  39. tmp = tmp + (int64_t)val1 / 2ll;
  40. tmp /= (int64_t)val1;
  41. return (fixpt_t)(int32_t)tmp;
  42. }
  43. #define FIXPT_BIAS(val, bias) \
  44. (fixpt_is_neg(val) ? \
  45. fixpt_sub(val, FLOAT_TO_FIXPT(bias)) : \
  46. fixpt_add(val, FLOAT_TO_FIXPT(bias)))
  47. #define FIXPT_ARG_PREFIX(val, bias) \
  48. (fixpt_is_neg(FIXPT_BIAS(val, bias)) ? "-" : "")
  49. #define FIXPT_ARG_INTPART(val, bias) \
  50. ((int)fixpt_abs(FIXPT_INT_PART(FIXPT_BIAS(val, bias))))
  51. #define FIXPT_ARG_FRACPART(val, mult, bias) \
  52. ((unsigned int)((FIXPT_FRAC_PART(FIXPT_BIAS(val, bias)) \
  53. * (mult)) / (FIXPT_FRAC_MASK + 1)))
  54. #define FIXPT_ARG_FULL(val, mult, bias) \
  55. FIXPT_ARG_PREFIX(val, bias), \
  56. FIXPT_ARG_INTPART(val, bias), \
  57. FIXPT_ARG_FRACPART(val, mult, bias)
  58. #define FIXPT_ARG_INTONLY(val, bias) \
  59. FIXPT_ARG_PREFIX(val, bias), \
  60. FIXPT_ARG_INTPART(val, bias)
  61. /* printf() format and arguments for fixpt_t.
  62. * Note that val is evaluated multiple times. */
  63. #define FIXPT_FMT0 "%s%d"
  64. #define FIXPT_ARG0(val) FIXPT_ARG_INTONLY(val, 0.5)
  65. #define FIXPT_FMT1 "%s%d.%01u"
  66. #define FIXPT_ARG1(val) FIXPT_ARG_FULL(val, 10, 0.05)
  67. #define FIXPT_FMT2 "%s%d.%02u"
  68. #define FIXPT_ARG2(val) FIXPT_ARG_FULL(val, 100, 0.005)
  69. #define FIXPT_FMT3 "%s%d.%03u"
  70. #define FIXPT_ARG3(val) FIXPT_ARG_FULL(val, 1000, 0.0005)
  71. #define FIXPT_FMT4 "%s%d.%04u"
  72. #define FIXPT_ARG4(val) FIXPT_ARG_FULL(val, 10000, 0.00005)
  73. enum axis_id {
  74. AXIS_X,
  75. AXIS_Y,
  76. AXIS_Z,
  77. AXIS_U,
  78. AXIS_V,
  79. AXIS_W,
  80. AXIS_A,
  81. AXIS_B,
  82. AXIS_C,
  83. NR_AXIS,
  84. };
  85. static inline uint8_t axis_is_angular(enum axis_id id)
  86. {
  87. switch (id) {
  88. case AXIS_A:
  89. case AXIS_B:
  90. case AXIS_C:
  91. return 1;
  92. case AXIS_X:
  93. case AXIS_Y:
  94. case AXIS_Z:
  95. case AXIS_U:
  96. case AXIS_V:
  97. case AXIS_W:
  98. case NR_AXIS:
  99. break;
  100. }
  101. return 0;
  102. }
  103. enum control_id {
  104. CONTROL_PING, /* Pong request */
  105. CONTROL_RESET, /* Reset device state */
  106. CONTROL_DEVFLAGS, /* Update and read device flags */
  107. CONTROL_AXISUPDATE, /* Axis position update */
  108. CONTROL_SPINDLEUPDATE, /* Spindle state update */
  109. CONTROL_FOUPDATE, /* Feed override update */
  110. CONTROL_AXISENABLE, /* Set the axis-enable mask */
  111. CONTROL_ESTOPUPDATE, /* E-stop status update */
  112. CONTROL_SETINCREMENT, /* Upload an increment definition */
  113. /* Bootloader messages */
  114. CONTROL_ENTERBOOT = 0xA0, /* Enter the CPU/coprocessor bootloader */
  115. CONTROL_EXITBOOT, /* Exit CPU/coprocessor bootloader */
  116. CONTROL_BOOT_WRITEBUF, /* Write to the page buffer */
  117. CONTROL_BOOT_FLASHPG, /* Flash page buffer */
  118. CONTROL_BOOT_EEPWRITE, /* Write page buffer to eeprom */
  119. };
  120. enum control_message_flags {
  121. CONTROL_FLG_BOOTLOADER = 0x80, /* Intended message recipient is the bootloader */
  122. };
  123. enum device_flags {
  124. DEVICE_FLG_NODEBUG = (1ul << 0), /* Debugging disabled */
  125. DEVICE_FLG_VERBOSEDBG = (1ul << 1), /* Verbose debugging */
  126. DEVICE_FLG_ON = (1ul << 2), /* The CNC Control device is turned on */
  127. DEVICE_FLG_TWOHANDEN = (1ul << 3), /* Twohand switch enabled */
  128. DEVICE_FLG_USBLOGMSG = (1ul << 4), /* Send debug messages through USB */
  129. DEVICE_FLG_G53COORDS = (1ul << 5), /* Use machine coordinates */
  130. };
  131. enum enterboot_magic {
  132. ENTERBOOT_MAGIC0 = 0xB0,
  133. ENTERBOOT_MAGIC1 = 0x07,
  134. };
  135. enum mcu_target {
  136. TARGET_CPU, /* Target is the CPU */
  137. TARGET_COPROC, /* Target is the coprocessor */
  138. };
  139. enum spindle_state {
  140. SPINDLE_OFF,
  141. SPINDLE_CW,
  142. SPINDLE_CCW,
  143. };
  144. /* Control message from the CNC machine. */
  145. struct control_message {
  146. uint8_t id;
  147. uint8_t flags;
  148. uint8_t _reserved;
  149. uint8_t seqno;
  150. int _header_end[0];
  151. union {
  152. struct {
  153. } __packed ping;
  154. struct {
  155. uint16_t mask;
  156. uint16_t set;
  157. } __packed devflags;
  158. struct {
  159. fixpt_t pos;
  160. uint8_t axis;
  161. } __packed axisupdate;
  162. struct {
  163. uint8_t state;
  164. } __packed spindleupdate;
  165. struct {
  166. uint8_t percent;
  167. } __packed feedoverride;
  168. struct {
  169. uint16_t mask;
  170. } __packed axisenable;
  171. struct {
  172. uint8_t asserted;
  173. } __packed estopupdate;
  174. struct {
  175. fixpt_t increment;
  176. uint8_t index;
  177. } __packed setincrement;
  178. /* Bootloader messages */
  179. struct {
  180. uint8_t magic[2];
  181. uint8_t target; /* enum mcu_target */
  182. } __packed enterboot;
  183. struct {
  184. uint8_t target; /* enum mcu_target */
  185. } __packed exitboot;
  186. struct {
  187. uint16_t offset;
  188. uint8_t size;
  189. uint8_t crc;
  190. uint8_t data[32];
  191. } __packed boot_writebuf;
  192. struct {
  193. uint16_t address;
  194. uint8_t target; /* enum mcu_target */
  195. } __packed boot_flashpg;
  196. struct {
  197. uint16_t address;
  198. uint16_t size;
  199. uint8_t target; /* enum mcu_target */
  200. } __packed boot_eepwrite;
  201. } __packed;
  202. } __packed;
  203. #define CONTROL_MSG_SIZE(name) (offsetof(struct control_message, name) +\
  204. sizeof(((struct control_message *)0)->name))
  205. #define CONTROL_MSG_HDR_SIZE CONTROL_MSG_SIZE(_header_end)
  206. #define CONTROL_MSG_MAX_SIZE sizeof(struct control_message)
  207. static inline int control_enterboot_magic_ok(const struct control_message *ctl)
  208. {
  209. return (ctl->enterboot.magic[0] == ENTERBOOT_MAGIC0 &&
  210. ctl->enterboot.magic[1] == ENTERBOOT_MAGIC1);
  211. }
  212. enum reply_id {
  213. REPLY_OK,
  214. REPLY_ERROR,
  215. REPLY_VAL16,
  216. };
  217. enum reply_error {
  218. CTLERR_UNDEFINED, /* Undefined error */
  219. CTLERR_COMMAND, /* Unknown command */
  220. CTLERR_SIZE, /* Command size mismatch */
  221. CTLERR_BUSY, /* Busy / Action already committed */
  222. CTLERR_PERMISSION, /* Permission denied */
  223. CTLERR_INVAL, /* Invalid input data */
  224. CTLERR_CONTEXT, /* Invalid context (boot vs app) */
  225. CTLERR_CHECKSUM, /* Checksum/parity error */
  226. CTLERR_CMDFAIL, /* Command failed */
  227. };
  228. /* Control reply to the CNC machine. */
  229. struct control_reply {
  230. uint8_t id;
  231. uint8_t flags;
  232. uint8_t _reserved;
  233. uint8_t seqno;
  234. int _header_end[0];
  235. union {
  236. struct {
  237. } __packed ok;
  238. struct {
  239. uint8_t code;
  240. } __packed error;
  241. struct {
  242. uint16_t value;
  243. } __packed val16;
  244. } __packed;
  245. } __packed;
  246. #define CONTROL_REPLY_SIZE(name) (offsetof(struct control_reply, name) +\
  247. sizeof(((struct control_reply *)0)->name))
  248. #define CONTROL_REPLY_HDR_SIZE CONTROL_REPLY_SIZE(_header_end)
  249. #define CONTROL_REPLY_MAX_SIZE sizeof(struct control_reply)
  250. static inline void init_control_reply(struct control_reply *reply,
  251. uint8_t id, uint8_t flags, uint8_t seqno)
  252. {
  253. reply->id = id;
  254. reply->flags = flags;
  255. reply->_reserved = 0;
  256. reply->seqno = seqno;
  257. }
  258. enum interrupt_id {
  259. IRQ_JOG, /* Jog control */
  260. IRQ_JOG_KEEPALIFE, /* Jog keepalife request */
  261. IRQ_SPINDLE, /* Turn the master spindle on/off */
  262. IRQ_FEEDOVERRIDE, /* Change the feed override */
  263. IRQ_DEVFLAGS, /* Device flags changed. */
  264. IRQ_HALT, /* Halt motion */
  265. IRQ_LOGMSG, /* Log message */
  266. };
  267. enum control_irq_flags {
  268. IRQ_FLG_TXQOVR = (1 << 0), /* TX queue overflow */
  269. IRQ_FLG_PRIO = (1 << 1), /* Higher priority */
  270. IRQ_FLG_DROPPABLE = (1 << 2), /* May be dropped in favor of higher prio irqs */
  271. };
  272. enum jogirq_flags {
  273. IRQ_JOG_CONTINUOUS = (1 << 0), /* Continuous jog */
  274. IRQ_JOG_RAPID = (1 << 1), /* Rapid jog */
  275. };
  276. /* Device interrupt. */
  277. struct control_interrupt {
  278. uint8_t id;
  279. uint8_t flags;
  280. uint8_t _reserved;
  281. uint8_t seqno;
  282. int _header_end[0];
  283. union {
  284. struct {
  285. fixpt_t increment;
  286. fixpt_t velocity;
  287. uint8_t axis;
  288. uint8_t flags;
  289. } __packed jog;
  290. struct {
  291. } __packed jog_keepalife;
  292. struct {
  293. uint8_t state;
  294. } __packed spindle;
  295. struct {
  296. uint8_t state;
  297. } __packed feedoverride;
  298. struct {
  299. uint16_t flags;
  300. } __packed devflags;
  301. struct {
  302. } __packed halt;
  303. struct {
  304. uint8_t msg[10];
  305. } __packed logmsg;
  306. } __packed;
  307. } __packed;
  308. #define CONTROL_IRQ_SIZE(name) (offsetof(struct control_interrupt, name) +\
  309. sizeof(((struct control_interrupt *)0)->name))
  310. #define CONTROL_IRQ_HDR_SIZE CONTROL_IRQ_SIZE(_header_end)
  311. #define CONTROL_IRQ_MAX_SIZE sizeof(struct control_interrupt)
  312. #endif /* MACHINE_INTERFACE_H_ */