123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- #ifndef MACHINE_INTERFACE_H_
- #define MACHINE_INTERFACE_H_
- /*** The CNC-machine interface ***/
- #include <stdint.h>
- #undef __packed
- #define __packed __attribute__((__packed__))
- /* Fixed point arithmetics */
- typedef int32_t fixpt_t;
- #define FIXPT_FRAC_BITS 16
- #define FIXPT_FRAC_MASK (((uint32_t)1 << FIXPT_FRAC_BITS) - 1)
- #define FIXPT_INT_PART(val) (((int32_t)(val) >> FIXPT_FRAC_BITS) + (fixpt_is_neg(val) ? 1 : 0))
- #define FIXPT_FRAC_PART(val) ((uint32_t)fixpt_abs(val) & FIXPT_FRAC_MASK)
- #define TO_FIXPT(val) ((fixpt_t)(int32_t)(val))
- /* Fixed point arithmetics conversion helpers */
- #define FLOAT_TO_FIXPT(f) TO_FIXPT(((float)(f)) * (FIXPT_FRAC_MASK + 1) + 1)
- #define INT32_TO_FIXPT(i) TO_FIXPT(((uint32_t)(int32_t)(i)) << FIXPT_FRAC_BITS)
- #define fixpt_add(val0, val1) ((fixpt_t)((int32_t)(val0) + (int32_t)(val1)))
- #define fixpt_sub(val0, val1) ((fixpt_t)((int32_t)(val0) - (int32_t)(val1)))
- #define fixpt_is_neg(val) ((int32_t)(val) < 0)
- #define fixpt_neg(val) ((fixpt_t)(-((int32_t)(val))))
- static inline fixpt_t fixpt_abs(fixpt_t val)
- {
- if (fixpt_is_neg(val))
- return fixpt_neg(val);
- return val;
- }
- static inline fixpt_t fixpt_mult(fixpt_t val0, fixpt_t val1)
- {
- int64_t tmp;
- tmp = (int64_t)val0 * (int64_t)val1;
- tmp += (1ll << (FIXPT_FRAC_BITS - 1));
- tmp >>= FIXPT_FRAC_BITS;
- return (fixpt_t)(int32_t)tmp;
- }
- static inline fixpt_t fixpt_div(fixpt_t val0, fixpt_t val1)
- {
- int64_t tmp;
- tmp = (int64_t)val0 << FIXPT_FRAC_BITS;
- tmp = tmp + (int64_t)val1 / 2ll;
- tmp /= (int64_t)val1;
- return (fixpt_t)(int32_t)tmp;
- }
- #define FIXPT_BIAS(val, bias) \
- (fixpt_is_neg(val) ? \
- fixpt_sub(val, FLOAT_TO_FIXPT(bias)) : \
- fixpt_add(val, FLOAT_TO_FIXPT(bias)))
- #define FIXPT_ARG_PREFIX(val, bias) \
- (fixpt_is_neg(FIXPT_BIAS(val, bias)) ? "-" : "")
- #define FIXPT_ARG_INTPART(val, bias) \
- ((int)fixpt_abs(FIXPT_INT_PART(FIXPT_BIAS(val, bias))))
- #define FIXPT_ARG_FRACPART(val, mult, bias) \
- ((unsigned int)((FIXPT_FRAC_PART(FIXPT_BIAS(val, bias)) \
- * (mult)) / (FIXPT_FRAC_MASK + 1)))
- #define FIXPT_ARG_FULL(val, mult, bias) \
- FIXPT_ARG_PREFIX(val, bias), \
- FIXPT_ARG_INTPART(val, bias), \
- FIXPT_ARG_FRACPART(val, mult, bias)
- #define FIXPT_ARG_INTONLY(val, bias) \
- FIXPT_ARG_PREFIX(val, bias), \
- FIXPT_ARG_INTPART(val, bias)
- /* printf() format and arguments for fixpt_t.
- * Note that val is evaluated multiple times. */
- #define FIXPT_FMT0 "%s%d"
- #define FIXPT_ARG0(val) FIXPT_ARG_INTONLY(val, 0.5)
- #define FIXPT_FMT1 "%s%d.%01u"
- #define FIXPT_ARG1(val) FIXPT_ARG_FULL(val, 10, 0.05)
- #define FIXPT_FMT2 "%s%d.%02u"
- #define FIXPT_ARG2(val) FIXPT_ARG_FULL(val, 100, 0.005)
- #define FIXPT_FMT3 "%s%d.%03u"
- #define FIXPT_ARG3(val) FIXPT_ARG_FULL(val, 1000, 0.0005)
- #define FIXPT_FMT4 "%s%d.%04u"
- #define FIXPT_ARG4(val) FIXPT_ARG_FULL(val, 10000, 0.00005)
- enum axis_id {
- AXIS_X,
- AXIS_Y,
- AXIS_Z,
- AXIS_U,
- AXIS_V,
- AXIS_W,
- AXIS_A,
- AXIS_B,
- AXIS_C,
- NR_AXIS,
- };
- static inline uint8_t axis_is_angular(enum axis_id id)
- {
- switch (id) {
- case AXIS_A:
- case AXIS_B:
- case AXIS_C:
- return 1;
- case AXIS_X:
- case AXIS_Y:
- case AXIS_Z:
- case AXIS_U:
- case AXIS_V:
- case AXIS_W:
- case NR_AXIS:
- break;
- }
- return 0;
- }
- enum control_id {
- CONTROL_PING, /* Pong request */
- CONTROL_RESET, /* Reset device state */
- CONTROL_DEVFLAGS, /* Update and read device flags */
- CONTROL_AXISUPDATE, /* Axis position update */
- CONTROL_SPINDLEUPDATE, /* Spindle state update */
- CONTROL_FOUPDATE, /* Feed override update */
- CONTROL_AXISENABLE, /* Set the axis-enable mask */
- CONTROL_ESTOPUPDATE, /* E-stop status update */
- CONTROL_SETINCREMENT, /* Upload an increment definition */
- /* Bootloader messages */
- CONTROL_ENTERBOOT = 0xA0, /* Enter the CPU/coprocessor bootloader */
- CONTROL_EXITBOOT, /* Exit CPU/coprocessor bootloader */
- CONTROL_BOOT_WRITEBUF, /* Write to the page buffer */
- CONTROL_BOOT_FLASHPG, /* Flash page buffer */
- CONTROL_BOOT_EEPWRITE, /* Write page buffer to eeprom */
- };
- enum control_message_flags {
- CONTROL_FLG_BOOTLOADER = 0x80, /* Intended message recipient is the bootloader */
- };
- enum device_flags {
- DEVICE_FLG_NODEBUG = (1ul << 0), /* Debugging disabled */
- DEVICE_FLG_VERBOSEDBG = (1ul << 1), /* Verbose debugging */
- DEVICE_FLG_ON = (1ul << 2), /* The CNC Control device is turned on */
- DEVICE_FLG_TWOHANDEN = (1ul << 3), /* Twohand switch enabled */
- DEVICE_FLG_USBLOGMSG = (1ul << 4), /* Send debug messages through USB */
- DEVICE_FLG_G53COORDS = (1ul << 5), /* Use machine coordinates */
- };
- enum enterboot_magic {
- ENTERBOOT_MAGIC0 = 0xB0,
- ENTERBOOT_MAGIC1 = 0x07,
- };
- enum mcu_target {
- TARGET_CPU, /* Target is the CPU */
- TARGET_COPROC, /* Target is the coprocessor */
- };
- enum spindle_state {
- SPINDLE_OFF,
- SPINDLE_CW,
- SPINDLE_CCW,
- };
- /* Control message from the CNC machine. */
- struct control_message {
- uint8_t id;
- uint8_t flags;
- uint8_t _reserved;
- uint8_t seqno;
- int _header_end[0];
- union {
- struct {
- } __packed ping;
- struct {
- uint16_t mask;
- uint16_t set;
- } __packed devflags;
- struct {
- fixpt_t pos;
- uint8_t axis;
- } __packed axisupdate;
- struct {
- uint8_t state;
- } __packed spindleupdate;
- struct {
- uint8_t percent;
- } __packed feedoverride;
- struct {
- uint16_t mask;
- } __packed axisenable;
- struct {
- uint8_t asserted;
- } __packed estopupdate;
- struct {
- fixpt_t increment;
- uint8_t index;
- } __packed setincrement;
- /* Bootloader messages */
- struct {
- uint8_t magic[2];
- uint8_t target; /* enum mcu_target */
- } __packed enterboot;
- struct {
- uint8_t target; /* enum mcu_target */
- } __packed exitboot;
- struct {
- uint16_t offset;
- uint8_t size;
- uint8_t crc;
- uint8_t data[32];
- } __packed boot_writebuf;
- struct {
- uint16_t address;
- uint8_t target; /* enum mcu_target */
- } __packed boot_flashpg;
- struct {
- uint16_t address;
- uint16_t size;
- uint8_t target; /* enum mcu_target */
- } __packed boot_eepwrite;
- } __packed;
- } __packed;
- #define CONTROL_MSG_SIZE(name) (offsetof(struct control_message, name) +\
- sizeof(((struct control_message *)0)->name))
- #define CONTROL_MSG_HDR_SIZE CONTROL_MSG_SIZE(_header_end)
- #define CONTROL_MSG_MAX_SIZE sizeof(struct control_message)
- static inline int control_enterboot_magic_ok(const struct control_message *ctl)
- {
- return (ctl->enterboot.magic[0] == ENTERBOOT_MAGIC0 &&
- ctl->enterboot.magic[1] == ENTERBOOT_MAGIC1);
- }
- enum reply_id {
- REPLY_OK,
- REPLY_ERROR,
- REPLY_VAL16,
- };
- enum reply_error {
- CTLERR_UNDEFINED, /* Undefined error */
- CTLERR_COMMAND, /* Unknown command */
- CTLERR_SIZE, /* Command size mismatch */
- CTLERR_BUSY, /* Busy / Action already committed */
- CTLERR_PERMISSION, /* Permission denied */
- CTLERR_INVAL, /* Invalid input data */
- CTLERR_CONTEXT, /* Invalid context (boot vs app) */
- CTLERR_CHECKSUM, /* Checksum/parity error */
- CTLERR_CMDFAIL, /* Command failed */
- };
- /* Control reply to the CNC machine. */
- struct control_reply {
- uint8_t id;
- uint8_t flags;
- uint8_t _reserved;
- uint8_t seqno;
- int _header_end[0];
- union {
- struct {
- } __packed ok;
- struct {
- uint8_t code;
- } __packed error;
- struct {
- uint16_t value;
- } __packed val16;
- } __packed;
- } __packed;
- #define CONTROL_REPLY_SIZE(name) (offsetof(struct control_reply, name) +\
- sizeof(((struct control_reply *)0)->name))
- #define CONTROL_REPLY_HDR_SIZE CONTROL_REPLY_SIZE(_header_end)
- #define CONTROL_REPLY_MAX_SIZE sizeof(struct control_reply)
- static inline void init_control_reply(struct control_reply *reply,
- uint8_t id, uint8_t flags, uint8_t seqno)
- {
- reply->id = id;
- reply->flags = flags;
- reply->_reserved = 0;
- reply->seqno = seqno;
- }
- enum interrupt_id {
- IRQ_JOG, /* Jog control */
- IRQ_JOG_KEEPALIFE, /* Jog keepalife request */
- IRQ_SPINDLE, /* Turn the master spindle on/off */
- IRQ_FEEDOVERRIDE, /* Change the feed override */
- IRQ_DEVFLAGS, /* Device flags changed. */
- IRQ_HALT, /* Halt motion */
- IRQ_LOGMSG, /* Log message */
- };
- enum control_irq_flags {
- IRQ_FLG_TXQOVR = (1 << 0), /* TX queue overflow */
- IRQ_FLG_PRIO = (1 << 1), /* Higher priority */
- IRQ_FLG_DROPPABLE = (1 << 2), /* May be dropped in favor of higher prio irqs */
- };
- enum jogirq_flags {
- IRQ_JOG_CONTINUOUS = (1 << 0), /* Continuous jog */
- IRQ_JOG_RAPID = (1 << 1), /* Rapid jog */
- };
- /* Device interrupt. */
- struct control_interrupt {
- uint8_t id;
- uint8_t flags;
- uint8_t _reserved;
- uint8_t seqno;
- int _header_end[0];
- union {
- struct {
- fixpt_t increment;
- fixpt_t velocity;
- uint8_t axis;
- uint8_t flags;
- } __packed jog;
- struct {
- } __packed jog_keepalife;
- struct {
- uint8_t state;
- } __packed spindle;
- struct {
- uint8_t state;
- } __packed feedoverride;
- struct {
- uint16_t flags;
- } __packed devflags;
- struct {
- } __packed halt;
- struct {
- uint8_t msg[10];
- } __packed logmsg;
- } __packed;
- } __packed;
- #define CONTROL_IRQ_SIZE(name) (offsetof(struct control_interrupt, name) +\
- sizeof(((struct control_interrupt *)0)->name))
- #define CONTROL_IRQ_HDR_SIZE CONTROL_IRQ_SIZE(_header_end)
- #define CONTROL_IRQ_MAX_SIZE sizeof(struct control_interrupt)
- #endif /* MACHINE_INTERFACE_H_ */
|