#ifndef COMM_H_ #define COMM_H_ #include "util.h" #include #include #ifndef COMM_PAYLOAD_LEN # define COMM_PAYLOAD_LEN 8 #endif #ifndef COMM_LOCAL_ADDRESS # define COMM_LOCAL_ADDRESS 0 #endif #ifndef COMM_BAUDRATE # define COMM_BAUDRATE 9600 #endif #ifndef COMM_TX_QUEUE_SIZE # define COMM_TX_QUEUE_SIZE 4 /* Must be power of two */ #endif #define COMM_TX_QUEUE_MASK (COMM_TX_QUEUE_SIZE - 1) #ifndef COMM_RX_QUEUE_SIZE # define COMM_RX_QUEUE_SIZE 4 /* Must be power of two */ #endif #define COMM_RX_QUEUE_MASK (COMM_RX_QUEUE_SIZE - 1) enum comm_frame_control { COMM_FC_RESET = 0x01, COMM_FC_REQ_ACK = 0x02, COMM_FC_ACK = 0x04, COMM_FC_ERRCODE = 0xC0, COMM_FC_ERRCODE_SHIFT = 6, }; enum comm_errcode { COMM_ERR_OK, /* Ok. */ COMM_ERR_FAIL, /* Failure. */ COMM_ERR_FCS, /* Checksum error. */ COMM_ERR_Q, /* Queue overflow. */ }; typedef uint16_t comm_crc_t; /* little endian checksum*/ #define COMM_HDR_LEN 4 #define COMM_FCS_LEN sizeof(comm_crc_t) struct comm_message { uint8_t fc; /* Frame control. */ uint8_t seq; /* Sequence number. */ uint8_t addr; /* Source and destination address. */ uint8_t reserved; uint8_t payload[COMM_PAYLOAD_LEN]; /* Payload. */ comm_crc_t fcs; /* Frame check sequence. */ } _packed; #define COMM_MSG_INIT() { \ .fc = 0, \ .seq = 0, \ .addr = COMM_LOCAL_ADDRESS & 0x0F, \ } #define COMM_MSG(_name) \ struct comm_message _name = COMM_MSG_INIT() static inline uint8_t comm_msg_err(const struct comm_message *msg) { return (msg->fc & COMM_FC_ERRCODE) >> COMM_FC_ERRCODE_SHIFT; } static inline void comm_msg_set_err(struct comm_message *msg, uint8_t err) { msg->fc = (msg->fc & ~COMM_FC_ERRCODE) | (err << COMM_FC_ERRCODE_SHIFT); } static inline uint8_t comm_msg_sa(const struct comm_message *msg) { return msg->addr & 0x0F; } static inline void comm_msg_set_sa(struct comm_message *msg, uint8_t sa) { msg->addr = (msg->addr & 0xF0) | (sa & 0x0F); } static inline uint8_t comm_msg_da(const struct comm_message *msg) { return msg->addr >> 4; } static inline void comm_msg_set_da(struct comm_message *msg, uint8_t da) { msg->addr = (msg->addr & 0x0F) | (da << 4); } #define comm_payload(payload_ptr_type, msg) ((payload_ptr_type)((msg)->payload)) void comm_init(void); void comm_work(void); void comm_centisecond_tick(void); void comm_message_send(struct comm_message *msg, uint8_t dest_addr); void comm_drain_tx_queue(void); extern bool comm_handle_rx_message(const struct comm_message *msg, void *reply_payload); #endif /* COMM_H_ */