diff --git a/src/controller/controller.ino b/src/controller/controller.ino index 782134f..87ec1d4 100644 --- a/src/controller/controller.ino +++ b/src/controller/controller.ino @@ -1,42 +1,40 @@ -#include -#include +#include "shared.hpp" +#include "obus_can.hpp" -#include "../shared/shared.hpp" #define STATE_INACTIVE 0 #define STATE_HELLO 1 #define STATE_GAME 2 -#define OBUS_GAME_DURATION 60 // Duration of the game in seconds -#define OBUS_MAX_STRIKEOUTS 3 // Number of strikeouts allowed until game over +#define OBUS_MAX_STRIKES 3 // Number of strikes allowed until game over +#define OBUS_GAME_DURATION 10 // Duration of the game in seconds -MCP2515 mcp2515(10); +#define OBUS_GAME_DURATION_MS ((uint32_t) OBUS_GAME_DURATION*1000) + uint8_t state = STATE_INACTIVE; struct module connected_modules_ids[OBUS_MAX_MODULES]; uint8_t nr_connected_modules; -uint8_t strikeouts; +uint8_t strikes; // Bit vectors for checking if game is solved or not uint8_t unsolved_puzzles[32]; // 256 bits // TIMERS -uint16_t hello_round_start; -uint16_t game_start; -uint16_t last_update; +uint32_t hello_round_start; +uint32_t game_start; +uint32_t last_update; -struct module this_module = (struct module) { - .type = OBUS_TYPE_CONTROLLER; - .id = OBUS_CONTROLLER_ID; +struct module this_module = { + .type = OBUS_TYPE_CONTROLLER, + .id = OBUS_CONTROLLER_ID }; void setup() { Serial.begin(9600); - mcp2515.reset(); - mcp2515.setBitrate(CAN_50KBPS); - mcp2515.setNormalMode(); + obuscan_init(); state = STATE_INACTIVE; } @@ -44,7 +42,7 @@ void setup() { uint8_t check_solved() { uint8_t solved = 1; - for (int i; i<32; i++) { + for (uint8_t i = 0; i < 32; i++) { if (unsolved_puzzles != 0) { solved = 0; break; @@ -68,68 +66,48 @@ void solve_module_in_bit_vector(uint8_t module_id) { } -void send_message(uint8_t* message, uint8_t length) { - send_message(message, length, false); -} -void send_message(uint8_t* message, uint8_t length, bool priority) { - struct can_frame send_frame; - - send_frame.can_id = encode_can_id(this_module, priority); - send_frame.can_dlc = length; - - memcpy(send_frame.data, message, OBUS_MSG_LENGTH); - - mcp2515.sendMessage(&send_frame); -} - - void start_hello() { state = STATE_HELLO; hello_round_start = millis(); nr_connected_modules = 0; // Zero bit vectors - for (int i; i<32; i++) { + for (uint8_t i = 0; i < 32; i++) { unsolved_puzzles[i] = 0; } - uint8_t message[OBUS_MSG_LENGTH]; - message[0] = OBUS_MSGTYPE_C_HELLO; + struct obus_message msg = obuscan_msg_c_hello(this_module); + obuscan_send(&msg); - send_message(message, 1); - - Serial.println("Start of discovery round"); + Serial.println(F("Start of discovery round")); } void send_ack() { - uint8_t message[OBUS_MSG_LENGTH]; - message[0] = OBUS_MSGTYPE_C_ACK; - - send_message(message, 1); + struct obus_message msg = obuscan_msg_c_ack(this_module); + obuscan_send(&msg); } void receive_hello() { - struct can_frame receive_frame; - uint16_t current_time = millis(); + struct obus_message msg; + uint32_t current_time = millis(); - if (mcp2515.readMessage(&receive_frame) == MCP2515::ERROR_OK) { - if (receive_frame.data[0] == OBUS_MSGTYPE_M_HELLO) { - struct module new_module = decode_can_id(receive_frame.can_id); + if (obuscan_receive(&msg)) { + if (msg.msg_type == OBUS_MSGTYPE_M_HELLO) { Serial.print("Registered module "); - Serial.println(full_module_id(new_module)); - connected_modules_ids[nr_connected_modules] = new_module; + Serial.println(full_module_id(msg.from)); + connected_modules_ids[nr_connected_modules] = msg.from; nr_connected_modules++; - if (new_module.type == OBUS_TYPE_PUZZLE) { - add_module_to_bit_vector(full_module_id(new_module)); + if (msg.from.type == OBUS_TYPE_PUZZLE) { + add_module_to_bit_vector(full_module_id(msg.from)); } send_ack(); Serial.println("ACK"); } - } else if (current_time - hello_round_start > OBUS_DISC_DURATION * 1000) { + } else if (current_time - hello_round_start > OBUS_DISC_DURATION_MS) { Serial.println("End of discovery round"); initialize_game(); } @@ -137,86 +115,87 @@ void receive_hello() { void initialize_game() { - strikeouts = 0; - - uint16_t game_duration_millis = (uint16_t) OBUS_GAME_DURATION * 1000; - - uint8_t message[OBUS_MSG_LENGTH]; - message[0] = OBUS_MSGTYPE_C_GAMESTART; - message[1] = (uint8_t) ((game_duration_millis & 0xFF000000) >> 0x18); - message[2] = (uint8_t) ((game_duration_millis & 0x00FF0000) >> 0x10); - message[3] = (uint8_t) ((game_duration_millis & 0x0000FF00) >> 0x08); - message[4] = (uint8_t) (game_duration_millis & 0x000000FF); - message[5] = strikeouts; - message[6] = OBUS_MAX_STRIKEOUTS; - - send_message(message, 7); - + strikes = 0; game_start = millis(); - last_update = game_start; + last_update = game_start; state = STATE_GAME; Serial.println("Game started"); + + send_game_update(OBUS_MSGTYPE_C_GAMESTART, OBUS_GAME_DURATION_MS); } void receive_module_update() { - struct can_frame receive_frame; + struct obus_message msg; - if (mcp2515.readMessage(&receive_frame) == MCP2515::ERROR_OK) { - if (receive_frame.data[0] == OBUS_MSGTYPE_M_STRIKE) { - strikeouts++; - } else if (receive_frame.data[0] == OBUS_MSGTYPE_M_SOLVED) { - uint16_t module_id = full_module_id(decode_can_id(receive_frame.can_id)); - solve_module_in_bit_vector(module_id); + if (obuscan_receive(&msg)) { + + switch (msg.msg_type) { + case OBUS_MSGTYPE_M_STRIKE: + // TODO check idempotency ID + strikes++; + break; + + case OBUS_MSGTYPE_M_SOLVED: + solve_module_in_bit_vector(full_module_id(msg.from)); + break; + + default: + Serial.print(F("W Ignoring msg ")); + Serial.println(msg.msg_type); + break; } + } } -void send_game_update(uint8_t status, uint16_t timestamp) { - uint8_t message[OBUS_MSG_LENGTH]; - message[0] = status; - message[1] = (uint8_t) ((timestamp & 0xFF000000) >> 0x18); - message[2] = (uint8_t) ((timestamp & 0x00FF0000) >> 0x10); - message[3] = (uint8_t) ((timestamp & 0x0000FF00) >> 0x08); - message[4] = (uint8_t) (timestamp & 0x000000FF); - message[5] = strikeouts; - message[6] = OBUS_MAX_STRIKEOUTS; +void send_game_update(uint8_t msg_type, uint32_t time_left) { + Serial.print(F("Send ")); + Serial.print(msg_type); + Serial.print(F(": ")); + Serial.print(time_left); + Serial.print(F(", ")); + Serial.print(strikes); + Serial.print(F("/")); + Serial.println(OBUS_MAX_STRIKES); - send_message(message, 7); + struct obus_message msg = obuscan_msg_c_payld_gamestatus( + this_module, false, msg_type, time_left, strikes, OBUS_MAX_STRIKES); + obuscan_send(&msg); } void game_loop() { - uint16_t current_time = millis(); - uint16_t game_duration = current_time - game_start; + uint32_t current_time = millis(); + uint32_t time_elapsed = current_time - game_start; + uint32_t time_left = + OBUS_GAME_DURATION_MS < time_elapsed ? 0 : OBUS_GAME_DURATION_MS - time_elapsed; + // We cannot check for '<= 0' in an uint type so we check the terms prior to subtraction receive_module_update(); if (check_solved()) { Serial.println("Game solved"); - send_game_update(OBUS_MSGTYPE_C_SOLVED, game_duration); + send_game_update(OBUS_MSGTYPE_C_SOLVED, time_left); state = STATE_INACTIVE; return; - } else if (game_duration >= (uint16_t) OBUS_GAME_DURATION * 1000) { + } else if (time_left == 0) { Serial.println("Time's up"); - send_game_update(OBUS_MSGTYPE_C_TIMEOUT, game_duration); + send_game_update(OBUS_MSGTYPE_C_TIMEOUT, time_left); state = STATE_INACTIVE; return; - } else if (strikeouts >= OBUS_MAX_STRIKEOUTS) { + } else if (strikes >= OBUS_MAX_STRIKES) { Serial.println("Strikeout"); - send_game_update(OBUS_MSGTYPE_C_STRIKEOUT, game_duration); + send_game_update(OBUS_MSGTYPE_C_STRIKEOUT, time_left); state = STATE_INACTIVE; return; } - uint16_t elapsed_time = current_time - last_update; - if (elapsed_time > OBUS_UPDATE_INTERVAL) { - Serial.print("Sending game update: "); - Serial.println(game_duration); - send_game_update(OBUS_MSGTYPE_C_STATE, (uint16_t) OBUS_GAME_DURATION * 1000 - game_duration); + if (last_update + OBUS_UPDATE_INTERVAL <= current_time) { + send_game_update(OBUS_MSGTYPE_C_STATE, time_left); last_update = current_time; } } diff --git a/src/controller/obus_can.cpp b/src/controller/obus_can.cpp new file mode 100644 index 0000000..e9f2964 --- /dev/null +++ b/src/controller/obus_can.cpp @@ -0,0 +1,259 @@ +#include +#include + +#include "obus_can.hpp" + + +MCP2515 mcp2515(10); +bool obuscan_is_init = false; + + +uint16_t _encode_can_id(struct module mod, bool priority) { + assert(mod.type <= 0b11); + + /* b bb bbbbbbbb + * ↓ type module ID + * priority bit + */ + return \ + ((uint16_t) (priority ? CAN_DOMINANT : CAN_RECESSIVE) << 10) | \ + ((uint16_t) mod.type << 8) | \ + (uint16_t) mod.id; +} + +void _decode_can_id(uint16_t can_id, struct module *mod, bool *priority) { + *priority = ((can_id >> 10) & 1) == CAN_DOMINANT; + mod->type = (can_id >> 8) & 0b11; + mod->id = can_id & 0b11111111; + + assert(mod->type <= 0b11); +} + + +void obuscan_init() { + obuscan_is_init = true; + mcp2515.reset(); + mcp2515.setBitrate(CAN_50KBPS); + mcp2515.setNormalMode(); +} + + +void obuscan_send(struct obus_message *msg) { + if (!obuscan_is_init) { + Serial.println(F("Call obuscan_init first")); + return; + } + + struct can_frame send_frame; + + memset(&send_frame.data, 0, CAN_MAX_DLEN); + + uint8_t length = 1; + send_frame.data[0] = msg->msg_type; + + switch (msg->payload_type) { + case OBUS_PAYLDTYPE_EMPTY: break; + case OBUS_PAYLDTYPE_GAMESTATUS: + send_frame.data[1] = (uint8_t) ((msg->gamestatus.time_left & 0xFF000000) >> 0x18); + send_frame.data[2] = (uint8_t) ((msg->gamestatus.time_left & 0x00FF0000) >> 0x10); + send_frame.data[3] = (uint8_t) ((msg->gamestatus.time_left & 0x0000FF00) >> 0x08); + send_frame.data[4] = (uint8_t) (msg->gamestatus.time_left & 0x000000FF); + send_frame.data[5] = msg->gamestatus.strikes; + send_frame.data[6] = msg->gamestatus.max_strikes; + length = 7; + } + + send_frame.can_id = _encode_can_id(msg->from, msg->priority); + send_frame.can_dlc = length; + + mcp2515.sendMessage(&send_frame); +} + + +bool obuscan_receive(struct obus_message *msg) { + if (!obuscan_is_init) { + Serial.println(F("Call obuscan_init first")); + return false; + } + + struct can_frame receive_frame; + + memset(&receive_frame.data, 0, CAN_MAX_DLEN); + + MCP2515::ERROR status = mcp2515.readMessage(&receive_frame); + if (status != MCP2515::ERROR_OK) { + return false; + } + + // Always at least OBUS message type required + if (receive_frame.can_dlc < 1) { + Serial.println(F("W Received illegal msg: payload <1")); + return false; + } + + uint8_t msg_type = receive_frame.data[0]; + uint8_t payload_type = -1; + + _decode_can_id(receive_frame.can_id, &msg->from, &msg->priority); + // Controller messages + // TODO ifdef, ignore not for us and assume for us + if (msg->from.type == OBUS_TYPE_CONTROLLER) { + switch (msg_type) { + case OBUS_MSGTYPE_C_ACK: // fall-through + case OBUS_MSGTYPE_C_HELLO: + payload_type = OBUS_PAYLDTYPE_EMPTY; + break; + + case OBUS_MSGTYPE_C_GAMESTART: // fall-through + case OBUS_MSGTYPE_C_STATE: + case OBUS_MSGTYPE_C_SOLVED: + case OBUS_MSGTYPE_C_TIMEOUT: + case OBUS_MSGTYPE_C_STRIKEOUT: + payload_type = OBUS_PAYLDTYPE_GAMESTATUS; + break; + + default: + return false; + break; + } + + // Module messages + } else { + switch (msg_type) { + case OBUS_MSGTYPE_M_STRIKE: + payload_type = OBUS_PAYLDTYPE_IDEMPOTENCY_ID; + break; + + case OBUS_MSGTYPE_M_HELLO: + case OBUS_MSGTYPE_M_SOLVED: + payload_type = OBUS_PAYLDTYPE_EMPTY; + break; + + default: + return false; + break; + } + } + + switch (payload_type) { + case OBUS_PAYLDTYPE_EMPTY: + break; + + case OBUS_PAYLDTYPE_GAMESTATUS: + if (receive_frame.can_dlc < 7) { + Serial.println(F("W Received illegal gamestatus msg: payload <7")); + return false; + } + msg->gamestatus.time_left = + ((uint32_t) receive_frame.data[1] << 0x18) | + ((uint32_t) receive_frame.data[2] << 0x10) | + ((uint32_t) receive_frame.data[3] << 0x08) | + ((uint32_t) receive_frame.data[4]); + msg->gamestatus.strikes = receive_frame.data[5]; + msg->gamestatus.max_strikes = receive_frame.data[6]; + break; + + case OBUS_PAYLDTYPE_IDEMPOTENCY_ID: + msg->idempotency.id = receive_frame.data[1]; + break; + + default: + assert(false); + break; + } + + msg->msg_type = msg_type; + msg->payload_type = payload_type; + + return true; +} + + +inline struct obus_message _obuscan_msg( + struct module from, bool priority, uint8_t msg_type, uint8_t payload_type) { + + struct obus_message msg; + msg.from = from; + msg.priority = priority; + msg.msg_type = msg_type; + msg.payload_type = payload_type; + return msg; +} + + +struct obus_message obuscan_msg_c_payld_gamestatus( + struct module from, bool priority, uint8_t msg_type, + uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + + assert(from.type == OBUS_TYPE_CONTROLLER); + + struct obus_message msg = _obuscan_msg( + from, priority, msg_type, OBUS_PAYLDTYPE_GAMESTATUS); + msg.gamestatus.time_left = time_left; + msg.gamestatus.strikes = strikes; + msg.gamestatus.max_strikes = max_strikes; + return msg; +} + + +struct obus_message obuscan_msg_c_ack(struct module from) { + assert(from.type == OBUS_TYPE_CONTROLLER); + return _obuscan_msg(from, false, OBUS_MSGTYPE_C_ACK, OBUS_PAYLDTYPE_EMPTY); +} + +struct obus_message obuscan_msg_c_hello(struct module from) { + assert(from.type == OBUS_TYPE_CONTROLLER); + return _obuscan_msg(from, false, OBUS_MSGTYPE_C_HELLO, OBUS_PAYLDTYPE_EMPTY); +} + + +struct obus_message obuscan_msg_c_gamestart( + struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + + return obuscan_msg_c_payld_gamestatus( + from, false, OBUS_MSGTYPE_C_GAMESTART, time_left, strikes, max_strikes); +} + +struct obus_message obuscan_msg_c_state( + struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + + return obuscan_msg_c_payld_gamestatus( + from, false, OBUS_MSGTYPE_C_STATE, time_left, strikes, max_strikes); +} + +struct obus_message obuscan_msg_c_solved( + struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + + return obuscan_msg_c_payld_gamestatus( + from, false, OBUS_MSGTYPE_C_SOLVED, time_left, strikes, max_strikes); +} + +struct obus_message obuscan_msg_c_timeout( + struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + + return obuscan_msg_c_payld_gamestatus( + from, false, OBUS_MSGTYPE_C_TIMEOUT, time_left, strikes, max_strikes); +} + +struct obus_message obuscan_msg_c_strikeout( + struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + + return obuscan_msg_c_payld_gamestatus( + from, false, OBUS_MSGTYPE_C_STRIKEOUT, time_left, strikes, max_strikes); +} + + +struct obus_message obuscan_msg_m_hello(struct module from) { + assert(from.type != OBUS_TYPE_CONTROLLER); + return _obuscan_msg(from, false, OBUS_MSGTYPE_M_HELLO, OBUS_PAYLDTYPE_EMPTY); +} + +struct obus_message obuscan_msg_m_strike(struct module from) { + assert(from.type != OBUS_TYPE_CONTROLLER); + return _obuscan_msg(from, false, OBUS_MSGTYPE_M_STRIKE, OBUS_PAYLDTYPE_EMPTY); +} + +struct obus_message obuscan_msg_m_solved(struct module from) { + assert(from.type != OBUS_TYPE_CONTROLLER); + return _obuscan_msg(from, false, OBUS_MSGTYPE_M_STRIKE, OBUS_PAYLDTYPE_EMPTY); +} diff --git a/src/controller/obus_can.hpp b/src/controller/obus_can.hpp new file mode 100644 index 0000000..7378919 --- /dev/null +++ b/src/controller/obus_can.hpp @@ -0,0 +1,79 @@ +#ifndef OBUS_CAN_H +#define OBUS_CAN_H + +#define CAN_DOMINANT 0 +#define CAN_RECESSIVE 1 + +#define OBUS_CONTROLLER_ID 0x000 + +#define OBUS_MSG_LENGTH 8 // Max 8 to fit in a CAN message + +#define OBUS_TYPE_CONTROLLER 0 +#define OBUS_TYPE_PUZZLE 1 +#define OBUS_TYPE_NEEDY 2 + +#define OBUS_MSGTYPE_C_ACK 0 +#define OBUS_MSGTYPE_C_HELLO 1 +#define OBUS_MSGTYPE_C_GAMESTART 2 +#define OBUS_MSGTYPE_C_STATE 3 +#define OBUS_MSGTYPE_C_SOLVED 4 +#define OBUS_MSGTYPE_C_TIMEOUT 5 +#define OBUS_MSGTYPE_C_STRIKEOUT 6 + +#define OBUS_MSGTYPE_M_HELLO 0 +#define OBUS_MSGTYPE_M_STRIKE 1 +#define OBUS_MSGTYPE_M_SOLVED 2 + +#define OBUS_PAYLDTYPE_EMPTY 0 +#define OBUS_PAYLDTYPE_GAMESTATUS 1 +#define OBUS_PAYLDTYPE_IDEMPOTENCY_ID 2 + +struct module { + uint8_t type; + uint8_t id; +}; + +struct payld_empty {}; +struct payld_gamestatus { + uint32_t time_left; + uint8_t strikes; + uint8_t max_strikes; +}; +struct payld_idempotency { + uint8_t id; +}; + + +struct obus_message { + struct module from; + bool priority; + uint8_t msg_type; + uint8_t payload_type; + union { + struct payld_empty empty; + struct payld_gamestatus gamestatus; + struct payld_idempotency idempotency; + }; +}; + +void obuscan_init(); +void obuscan_send(struct obus_message *msg); +bool obuscan_receive(struct obus_message *msg); + +struct obus_message obuscan_msg_c_payld_gamestatus( + struct module from, bool priority, uint8_t msg_type, + uint32_t time_left, uint8_t strikes, uint8_t max_strikes); + +struct obus_message obuscan_msg_c_ack(struct module from); +struct obus_message obuscan_msg_c_hello(struct module from); +struct obus_message obuscan_msg_c_gamestart(struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes); +struct obus_message obuscan_msg_c_state(struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes); +struct obus_message obuscan_msg_c_solved(struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes); +struct obus_message obuscan_msg_c_timeout(struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes); +struct obus_message obuscan_msg_c_strikeout(struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes); + +struct obus_message obuscan_msg_m_hello(struct module from); +struct obus_message obuscan_msg_m_strike(struct module from); +struct obus_message obuscan_msg_m_solved(struct module from); + +#endif /* end of include guard: OBUS_CAN_H */ diff --git a/src/controller/shared.hpp b/src/controller/shared.hpp new file mode 100644 index 0000000..63effbb --- /dev/null +++ b/src/controller/shared.hpp @@ -0,0 +1,18 @@ +#ifndef OBUS_SHARED_H +#define OBUS_SHARED_H + +#include "obus_can.hpp" + +#define OBUS_MAX_MODULES 16 +#define OBUS_DISC_DURATION 5 // Duration of discovery round in seconds +#define OBUS_UPDATE_INTERVAL 500 // Number of milliseconds between game updates + +#define OBUS_DISC_DURATION_MS ((uint32_t) OBUS_DISC_DURATION*1000) + +uint16_t full_module_id(struct module mod) { + return \ + ((uint16_t) mod.type << 8) | \ + (uint16_t) mod.id; +} + +#endif /* end of include guard: OBUS_DEFS_H */ diff --git a/src/shared/shared.hpp b/src/shared/shared.hpp deleted file mode 100644 index 165e462..0000000 --- a/src/shared/shared.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef OBUS_SHARED_H -#define OBUS_SHARED_H - -#define OBUS_CONTROLLER_ID 0x000 - -#define OBUS_TYPE_CONTROLLER 0 -#define OBUS_TYPE_PUZZLE 1 -#define OBUS_TYPE_NEEDY 2 - -#define OBUS_MSG_LENGTH 8 // Max 8 to fit in a CAN message - -#define OBUS_MAX_MODULES 16 -#define OBUS_DISC_DURATION 5 // Duration of discovery round in seconds -#define OBUS_UPDATE_INTERVAL 500 // Number of milliseconds between game updates - -#define OBUS_MSGTYPE_C_ACK 0 -#define OBUS_MSGTYPE_C_HELLO 1 -#define OBUS_MSGTYPE_C_GAMESTART 2 -#define OBUS_MSGTYPE_C_STATE 3 -#define OBUS_MSGTYPE_C_SOLVED 4 -#define OBUS_MSGTYPE_C_TIMEOUT 5 -#define OBUS_MSGTYPE_C_STRIKEOUT 6 - -#define OBUS_MSGTYPE_M_HELLO 0 -#define OBUS_MSGTYPE_M_STRIKE 1 -#define OBUS_MSGTYPE_M_SOLVED 2 - -#define CAN_DOMINANT 0 -#define CAN_RECESSIVE 1 - -#define OBUS_MASK_PRIORITY = 0b10000000000 -#define OBUS_MASK_TYPE = 0b01100000000 -#define OBUS_MASK_ID = 0b00011111111 - -struct module { - uint8_t type; - uint8_t id; -}; - - -uint16_t encode_can_id(struct module mod, bool priority) { - assert(mod.type <= 0b11); - - /* b bb bbbbbbbb - * ↓ type module ID - * priority bit - */ - return \ - ((uint16_t) (priority ? CAN_DOMINANT : CAN_RECESSIVE) << 10) | \ - ((uint16_t) mod.type << 8) | \ - (uint16_t) mod.id; -} - -uint16_t full_module_id(struct module mod) { - return \ - ((uint16_t) mod.type << 8) | \ - (uint16_t) mod.id; -} - -struct module decode_can_id(uint16_t can_id) { - struct module mod; - mod.type = (can_id & OBUS_MASK_TYPE) >> 8; - mod.id = can_id & OBUS_MASK_ID; - - assert(mod.type <= 0x11); - - return mod; -} - -#endif /* end of include guard: OBUS_DEFS_H */