#ifndef COMM_H #define COMM_H #include #include #ifndef true #define true 1 #define false 0 #endif typedef enum { // No communication running. CS_NONE = 0, // Sending a message. CS_SENDING, // Receiving a message. CS_RECEIVING, // Delay after a communication. CS_DELAY } comm_state_t; typedef enum { /** * Unused, empty message slot. * * State transitions: * - MS_PROCESSING <- comm_create_msg * - MS_READY <- comm_check_and_store_received_message, broadcast * - MS_RECEIVED <- comm_check_and_store_received_message, received */ MS_UNUSED = 0x00, /** * Message has been received, ready to be processed. * * State transitions: * - MS_PROCESSING <- comm_get_next_msg * - MS_UNUSED <- comm_timing, timeout */ MS_RECEIVED, /** * Message is beeing processed. * * State transitions: * - MS_READY <- comm_msg_is_ready * - MS_UNUSED <- comm_timing, timeout */ MS_PROCESSING, /** * Message is ready to send. * * State transitions: * - MS_UNUSED <- comm_check_and_store_received_message, ack * - MS_UNUSED <- comm_timing, timeout * - MS_SENT <- comm_send_recv ??????? +++++++++ */ MS_READY, /** * Message has been sent. * * State transitions: * - MS_UNUSED <- comm_check_and_store_received_message, ack * - MS_UNUSED <- comm_timing, timeout, too many resends * - MS_READY <- comm_timing, timeout, resend */ MS_SENT, #if 0 /** * Mask to get the message state. */ MS_STATE_MASK = 0x07, /** * Value to add when resending a message. */ MS_RESEND_ADD = 0x10, /** * Number of bits to shift for resend count. */ MS_RESEND_SHIFT = 4, /** * Maximum resend count. */ MS_RESEND_END = 0x30, /** * Mask to get the resend count. */ MS_RESEND_MASK = 0x30, #endif } msg_state_t; typedef struct { uint8_t resend:4; uint8_t state:4; uint8_t timeout; uint8_t retries; } msg_info_t; typedef struct { node_address_t node_id; uint8_t nr; uint8_t type; } msg_ack_t; #define MSG_BUF_SIZE 8 typedef struct { message_t buffer[MSG_BUF_SIZE]; msg_info_t infos[MSG_BUF_SIZE]; msg_ack_t acks[MSG_BUF_SIZE]; message_t recvmsg; node_address_t my_addr; comm_state_t state; uint8_t delay; uint8_t send_delay; uint8_t prevrxd; int8_t sendmsgnr; uint8_t* ptr; uint8_t cnt; uint8_t totcnt; uint8_t send_err; // Counts ticks from 0 to 44 at 2250Hz, time0 resets at 50Hz. uint8_t time0; // Increases two times in one time0 cycle => 100Hz increase frequency. uint8_t time1; // Counts centiseconds from 0 to 99, may be set by the application. uint8_t time_cs; // Set to 1 when time_cs overflows, must be cleared by the application. uint8_t time_seconds_flag; uint8_t prev_msg_nr; uint8_t prev_ack_idx; uint16_t prng; uint8_t timeout; } comm_t; #if 0 extern volatile comm_t G_comm; #endif /** * Initialize the communication. */ void comm_init( node_address_t addr ); /** * Transform message into a reply. */ void comm_create_reply( message_t* pmsg, uint8_t type ); /** * Allocate and initialize a new message. * * After the message data has been filled call comm_msg_is_ready(). */ message_t* comm_create_msg( node_address_t dst, uint8_t type ); /** * Mark the essage to be ready to sent. * * After marking a message it will be sent as soon as possible. */ void comm_msg_is_ready( message_t* pmsg ); /** * Get next message to process. * * Returns the next message to be processed and marks it as beeing processed. * The application must create a reply to this message * and make it ready to send. * After the last message has been processed this function returns NULL. */ message_t* comm_get_next_msg(); /** * Create an empty reply and immediately make it ready to send. * * This function is mostly useful for replying with ACKs. */ void comm_empty_reply( message_t* pmsg, uint8_t msgtype ); /** * Periodically called from interrupt handler. * * The default weak linked implementation does nothing. * This function is useful for checking buttons etc. */ void comm_tick(); #endif // COMM_H