From d9d13fd84edad4499cd6ae8aa55e399e7c53272a Mon Sep 17 00:00:00 2001 From: redfast00 Date: Mon, 1 Feb 2021 13:40:39 +0100 Subject: [PATCH 1/7] Remove double function --- lib/obus_can.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/obus_can.h b/lib/obus_can.h index 3a3a420..5473909 100644 --- a/lib/obus_can.h +++ b/lib/obus_can.h @@ -215,15 +215,6 @@ inline void send_c_infostart(struct module from) { /** * Send a controller "strikeout" OBUS message */ -inline void send_c_infostart(struct module from) { - assert(from.type == OBUS_TYPE_CONTROLLER); - struct message msg = _msg(from, false, OBUS_MSGTYPE_C_INFOSTART); - send(&msg); -} - -/** - * Send a controller "info start" OBUS message - */ inline void send_c_strikeout( struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { From e04ec74d3ccb4f6b8970a7a02d850f737d0d2692 Mon Sep 17 00:00:00 2001 From: redfast00 Date: Mon, 1 Feb 2021 15:33:14 +0100 Subject: [PATCH 2/7] Make info and state optional callbacks --- lib/obus_module.cpp | 26 ++++++++++++++++++++------ lib/obus_module.h | 7 +++++-- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/obus_module.cpp b/lib/obus_module.cpp index 952a27f..783c3d1 100644 --- a/lib/obus_module.cpp +++ b/lib/obus_module.cpp @@ -99,7 +99,20 @@ void setup(uint8_t type, uint8_t id) { _resetState(); } -bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t [7])) { +void empty_callback_info(uint8_t info_id, uint8_t infomessage[7]) { + // Mark arguments as not used + (void)info_id; + (void)infomessage; +} + +void empty_callback_state(uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + // Mark arguments as not used + (void)time_left; + (void)strikes; + (void)max_strikes; +} + +bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes)) { // TODO this can be more efficient by only enabling error interrupts and // reacting to the interrupt instead of checking if the flag is set in a loop // We will need to fork our CAN library for this, because the needed functions are private. @@ -114,8 +127,9 @@ bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void } } - bool interesting_message = false; + bool received_message = false; if (obus_can::receive(message)) { + received_message = true; if (is_from_controller(message->from)) { switch (message->msg_type) { case OBUS_MSGTYPE_C_GAMESTART: @@ -137,7 +151,7 @@ bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void case OBUS_MSGTYPE_C_ACK: break; case OBUS_MSGTYPE_C_STATE: - interesting_message = true; + callback_state(message->gamestatus.time_left, message->gamestatus.strikes, message->gamestatus.max_strikes); break; default: break; @@ -151,12 +165,12 @@ bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void _ledLoop(); - return interesting_message; + return received_message; } -bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t [7])) { +bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes)) { // For now this is the same function - return loopPuzzle(message, callback_game_start, callback_game_stop, callback_info); + return loopPuzzle(message, callback_game_start, callback_game_stop, callback_info, callback_state); } bool loopInfo(obus_can::message* message, int (*info_generator)(uint8_t*)) { diff --git a/lib/obus_module.h b/lib/obus_module.h index 914e778..02d5650 100644 --- a/lib/obus_module.h +++ b/lib/obus_module.h @@ -12,9 +12,12 @@ namespace obus_module { void setup(uint8_t type, uint8_t id); -bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t [7])); +void empty_callback_info(uint8_t info_id, uint8_t infomessage[7]); +void empty_callback_state(uint32_t time_left, uint8_t strikes, uint8_t max_strikes); -bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t [7])); +bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes) = empty_callback_state); + +bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes) = empty_callback_state); bool loopInfo(obus_can::message* message, int (*info_generator)(uint8_t*)); From 57a27125878e0694d343687ea15714f45e18b1ed Mon Sep 17 00:00:00 2001 From: redfast00 Date: Mon, 1 Feb 2021 15:34:41 +0100 Subject: [PATCH 3/7] Remove empty callbacks from modules --- .../needy_testmodule_buttons/needy_testmodule_buttons.ino | 6 +----- .../puzzle_testmodule_buttons/puzzle_testmodule_buttons.ino | 6 +----- .../puzzle_testmodule_date/puzzle_testmodule_date.ino | 6 +----- 3 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/modules/needy_testmodule_buttons/needy_testmodule_buttons.ino b/src/modules/needy_testmodule_buttons/needy_testmodule_buttons.ino index d333ebe..cb1002d 100644 --- a/src/modules/needy_testmodule_buttons/needy_testmodule_buttons.ino +++ b/src/modules/needy_testmodule_buttons/needy_testmodule_buttons.ino @@ -20,7 +20,7 @@ uint32_t next_activation_time = 0; uint32_t trigger_time = 0; void loop() { - bool is_message_valid = obus_module::loopNeedy(&message, callback_game_start, callback_game_stop, callback_info); + bool is_message_valid = obus_module::loopNeedy(&message, callback_game_start, callback_game_stop); green_button.loop(); // Every second, have a 1/20 chance to trigger the countdown @@ -65,7 +65,3 @@ void callback_game_start() { void callback_game_stop() { } - -void callback_info(uint8_t info_id, uint8_t [7]) { - // Intentionally empty -} diff --git a/src/modules/puzzle_testmodule_buttons/puzzle_testmodule_buttons.ino b/src/modules/puzzle_testmodule_buttons/puzzle_testmodule_buttons.ino index 3c5f969..312e1cc 100644 --- a/src/modules/puzzle_testmodule_buttons/puzzle_testmodule_buttons.ino +++ b/src/modules/puzzle_testmodule_buttons/puzzle_testmodule_buttons.ino @@ -17,7 +17,7 @@ void setup() { obus_can::message message; void loop() { - bool received = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop, callback_info); + bool received = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop); // TODO handle update frames (not needed for this module, but could be useful as example code) red_button.loop(); @@ -41,7 +41,3 @@ void callback_game_start() { void callback_game_stop() { // Intentionally empty } - -void callback_info(uint8_t info_id, uint8_t [7]) { - // Intentionally empty -} diff --git a/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino b/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino index c94665b..3509a11 100644 --- a/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino +++ b/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino @@ -47,7 +47,7 @@ void setup() { obus_can::message message; void loop() { - bool received = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop, callback_info); + bool received = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop); // TODO handle update frames (not needed for this module, but could be useful as example code) solve_button.loop(); if (solve_button.getCount() > 0) { @@ -128,7 +128,3 @@ void callback_game_start() { void callback_game_stop() { // Intentionally empty } - -void callback_info(uint8_t info_id, uint8_t [7]) { - // Intentionally empty -} From 393b1c94ced83b90b5769b1ef26d66492179d594 Mon Sep 17 00:00:00 2001 From: redfast00 Date: Mon, 1 Feb 2021 15:59:46 +0100 Subject: [PATCH 4/7] Add puzzle_modules_solved to gamestate updates --- debugging_tool/server.py | 3 ++- docs/protocol.txt | 4 ++-- lib/obus_can.cpp | 14 ++++++++------ lib/obus_can.h | 24 +++++++++++++----------- lib/obus_module.cpp | 9 +++++---- lib/obus_module.h | 6 +++--- src/controller/controller.ino | 15 ++++++++++----- 7 files changed, 43 insertions(+), 32 deletions(-) diff --git a/debugging_tool/server.py b/debugging_tool/server.py index c8984e2..5b62a03 100644 --- a/debugging_tool/server.py +++ b/debugging_tool/server.py @@ -50,8 +50,9 @@ class Message: timeleft = self.payload[1] << 0x18 | self.payload[2] << 0x10 | self.payload[3] << 0x08 | self.payload[4] strikes = self.payload[5] max_strikes = self.payload[6] + solved_puzzle_modules = self.payload[7] - return f'{timeleft/1000:3.2f} {strikes:02}/{max_strikes:02}' + return f'{timeleft/1000:3.2f} {strikes:02}/{max_strikes:02} [{solved_puzzle_modules:02}]' def parse_message(self): sender_type = self.sender_type() diff --git a/docs/protocol.txt b/docs/protocol.txt index 0ef8eef..74230e8 100644 --- a/docs/protocol.txt +++ b/docs/protocol.txt @@ -57,13 +57,13 @@ Types for controller: - 3 state (every x ms – e.g. in the middle of each second) [ X B B B B B B B ] -------- - - - - time left ↓ ↓ reserved + time left ↓ ↓ #solved puzzle modules #strikes #max strikes - 4-6 solved, timeout, strikeout [ X B B B B B B B ] -------- - - - - end time ↓ ↓ reserved + end time ↓ ↓ #solved puzzle modules #strikes #max strikes - 7 info start diff --git a/lib/obus_can.cpp b/lib/obus_can.cpp index 421dd1a..6df9e73 100644 --- a/lib/obus_can.cpp +++ b/lib/obus_can.cpp @@ -114,13 +114,14 @@ bool receive(struct message *msg) { break; case OBUS_PAYLDTYPE_GAMESTATUS: - if (receive_frame.can_dlc < 7) { - Serial.println(F("W Received illegal gamestatus msg: payload <7")); + if (receive_frame.can_dlc < 8) { + Serial.println(F("W Received illegal gamestatus msg: payload <8")); return false; } - msg->gamestatus.time_left = unpack_4b_into_u32(&(receive_frame.data[1])); - msg->gamestatus.strikes = receive_frame.data[5]; - msg->gamestatus.max_strikes = receive_frame.data[6]; + msg->gamestatus.time_left = unpack_4b_into_u32(&(receive_frame.data[1])); + msg->gamestatus.strikes = receive_frame.data[5]; + msg->gamestatus.max_strikes = receive_frame.data[6]; + msg->gamestatus.puzzle_modules_solved = receive_frame.data[7]; break; case OBUS_PAYLDTYPE_COUNT: @@ -186,7 +187,8 @@ void send(struct message *msg) { pack_u32_into_4b(&(send_frame.data[1]), msg->gamestatus.time_left); send_frame.data[5] = msg->gamestatus.strikes; send_frame.data[6] = msg->gamestatus.max_strikes; - length = 7; + send_frame.data[7] = msg->gamestatus.puzzle_modules_solved; + length = 8; break; case OBUS_PAYLDTYPE_COUNT: diff --git a/lib/obus_can.h b/lib/obus_can.h index 5473909..5f3c6b4 100644 --- a/lib/obus_can.h +++ b/lib/obus_can.h @@ -51,6 +51,7 @@ struct payld_gamestatus { uint32_t time_left; uint8_t strikes; uint8_t max_strikes; + uint8_t puzzle_modules_solved; }; struct payld_infomessage { uint8_t len; @@ -128,12 +129,13 @@ inline struct message _msg(struct module from, bool priority, uint8_t msg_type) */ inline void _send_payld_gamestatus( struct module from, bool priority, uint8_t msg_type, - uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) { struct message msg = _msg(from, priority, msg_type); msg.gamestatus.time_left = time_left; msg.gamestatus.strikes = strikes; msg.gamestatus.max_strikes = max_strikes; + msg.gamestatus.puzzle_modules_solved = puzzle_modules_solved; send(&msg); } @@ -163,44 +165,44 @@ inline void send_c_hello(struct module from) { * Send a controller "game start" OBUS message */ inline void send_c_gamestart( - struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) { assert(from.type == OBUS_TYPE_CONTROLLER); _send_payld_gamestatus( - from, false, OBUS_MSGTYPE_C_GAMESTART, time_left, strikes, max_strikes); + from, false, OBUS_MSGTYPE_C_GAMESTART, time_left, strikes, max_strikes, puzzle_modules_solved); } /** * Send a controller "state" OBUS message */ inline void send_c_state( - struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) { assert(from.type == OBUS_TYPE_CONTROLLER); _send_payld_gamestatus( - from, false, OBUS_MSGTYPE_C_STATE, time_left, strikes, max_strikes); + from, false, OBUS_MSGTYPE_C_STATE, time_left, strikes, max_strikes, puzzle_modules_solved); } /** * Send a controller "solved" OBUS message */ inline void send_c_solved( - struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) { assert(from.type == OBUS_TYPE_CONTROLLER); _send_payld_gamestatus( - from, false, OBUS_MSGTYPE_C_SOLVED, time_left, strikes, max_strikes); + from, false, OBUS_MSGTYPE_C_SOLVED, time_left, strikes, max_strikes, puzzle_modules_solved); } /** * Send a controller "timeout" OBUS message */ inline void send_c_timeout( - struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) { assert(from.type == OBUS_TYPE_CONTROLLER); _send_payld_gamestatus( - from, false, OBUS_MSGTYPE_C_TIMEOUT, time_left, strikes, max_strikes); + from, false, OBUS_MSGTYPE_C_TIMEOUT, time_left, strikes, max_strikes, puzzle_modules_solved); } /** @@ -216,11 +218,11 @@ inline void send_c_infostart(struct module from) { * Send a controller "strikeout" OBUS message */ inline void send_c_strikeout( - struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { + struct module from, uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) { assert(from.type == OBUS_TYPE_CONTROLLER); _send_payld_gamestatus( - from, false, OBUS_MSGTYPE_C_STRIKEOUT, time_left, strikes, max_strikes); + from, false, OBUS_MSGTYPE_C_STRIKEOUT, time_left, strikes, max_strikes, puzzle_modules_solved); } diff --git a/lib/obus_module.cpp b/lib/obus_module.cpp index 783c3d1..fb1351b 100644 --- a/lib/obus_module.cpp +++ b/lib/obus_module.cpp @@ -105,14 +105,15 @@ void empty_callback_info(uint8_t info_id, uint8_t infomessage[7]) { (void)infomessage; } -void empty_callback_state(uint32_t time_left, uint8_t strikes, uint8_t max_strikes) { +void empty_callback_state(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) { // Mark arguments as not used (void)time_left; (void)strikes; (void)max_strikes; + (void)puzzle_modules_solved; } -bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes)) { +bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved)) { // TODO this can be more efficient by only enabling error interrupts and // reacting to the interrupt instead of checking if the flag is set in a loop // We will need to fork our CAN library for this, because the needed functions are private. @@ -151,7 +152,7 @@ bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void case OBUS_MSGTYPE_C_ACK: break; case OBUS_MSGTYPE_C_STATE: - callback_state(message->gamestatus.time_left, message->gamestatus.strikes, message->gamestatus.max_strikes); + callback_state(message->gamestatus.time_left, message->gamestatus.strikes, message->gamestatus.max_strikes, message->gamestatus.puzzle_modules_solved); break; default: break; @@ -168,7 +169,7 @@ bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void return received_message; } -bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes)) { +bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved)) { // For now this is the same function return loopPuzzle(message, callback_game_start, callback_game_stop, callback_info, callback_state); } diff --git a/lib/obus_module.h b/lib/obus_module.h index 02d5650..8327df0 100644 --- a/lib/obus_module.h +++ b/lib/obus_module.h @@ -13,11 +13,11 @@ namespace obus_module { void setup(uint8_t type, uint8_t id); void empty_callback_info(uint8_t info_id, uint8_t infomessage[7]); -void empty_callback_state(uint32_t time_left, uint8_t strikes, uint8_t max_strikes); +void empty_callback_state(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved); -bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes) = empty_callback_state); +bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) = empty_callback_state); -bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes) = empty_callback_state); +bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) = empty_callback_state); bool loopInfo(obus_can::message* message, int (*info_generator)(uint8_t*)); diff --git a/src/controller/controller.ino b/src/controller/controller.ino index d439ec9..9075e63 100644 --- a/src/controller/controller.ino +++ b/src/controller/controller.ino @@ -28,6 +28,7 @@ uint8_t state = STATE_INACTIVE; struct obus_can::module connected_modules_ids[OBUS_MAX_MODULES]; uint8_t nr_connected_modules; uint8_t nr_connected_puzzles; +uint8_t nr_solved_puzzles; uint8_t strikes; // Bitvector for checking if game is solved or not @@ -86,6 +87,9 @@ void add_puzzle_to_bit_vector(uint8_t module_id) { void solve_puzzle_in_bit_vector(uint8_t module_id) { uint8_t byte_index = module_id >> 3; uint8_t bit_index = module_id & 0x07; + if (unsolved_puzzles[byte_index] & (0x1 << bit_index)) { + nr_solved_puzzles++; + } unsolved_puzzles[byte_index] &= ~(0x1 << bit_index); } @@ -176,6 +180,7 @@ void receive_hello() { void initialize_game() { strikes = 0; + nr_solved_puzzles = 0; game_start = millis(); last_draw = 0; @@ -185,7 +190,7 @@ void initialize_game() { Serial.println(" Game started"); draw_display(millis(), OBUS_GAME_DURATION_MS); - obus_can::send_c_gamestart(this_module, OBUS_GAME_DURATION_MS, strikes, OBUS_MAX_STRIKES); + obus_can::send_c_gamestart(this_module, OBUS_GAME_DURATION_MS, strikes, OBUS_MAX_STRIKES, nr_solved_puzzles); } @@ -241,14 +246,14 @@ void game_loop() { if (check_solved()) { Serial.println(" Game solved"); - obus_can::send_c_solved(this_module, time_left, strikes, OBUS_MAX_STRIKES); + obus_can::send_c_solved(this_module, time_left, strikes, OBUS_MAX_STRIKES, nr_solved_puzzles); state = STATE_GAMEOVER; tm.displayText("dISArmEd"); return; } if (time_left == 0) { Serial.println(" Time's up"); - obus_can::send_c_timeout(this_module, time_left, strikes, OBUS_MAX_STRIKES); + obus_can::send_c_timeout(this_module, time_left, strikes, OBUS_MAX_STRIKES, nr_solved_puzzles); state = STATE_GAMEOVER; tm.displayText(" boo t"); // m @@ -258,7 +263,7 @@ void game_loop() { } if (strikes >= OBUS_MAX_STRIKES) { Serial.println(" Strikeout"); - obus_can::send_c_strikeout(this_module, time_left, strikes, OBUS_MAX_STRIKES); + obus_can::send_c_strikeout(this_module, time_left, strikes, OBUS_MAX_STRIKES, nr_solved_puzzles); state = STATE_GAMEOVER; tm.displayText(" boo S"); // m @@ -270,7 +275,7 @@ void game_loop() { draw_display(current_time, time_left); if (last_update + OBUS_UPDATE_INTERVAL <= current_time) { - obus_can::send_c_state(this_module, time_left, strikes, OBUS_MAX_STRIKES); + obus_can::send_c_state(this_module, time_left, strikes, OBUS_MAX_STRIKES, nr_solved_puzzles); last_update = current_time; } } From b7c2e856825637ba8783c98ca06af9338b03e6f8 Mon Sep 17 00:00:00 2001 From: redfast00 Date: Mon, 1 Feb 2021 16:33:14 +0100 Subject: [PATCH 5/7] Remove info callback in template, correct casing --- src/template_module/main.ino | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/template_module/main.ino b/src/template_module/main.ino index 6551a68..ad61c06 100644 --- a/src/template_module/main.ino +++ b/src/template_module/main.ino @@ -16,8 +16,8 @@ void setup() { obus_can::message message; void loop() { - bool is_message_valid = obus_module::loop_puzzle(&message, callback_game_start, callback_game_stop, callback_info); - // bool is_message_valid = obus_module::loop_needy(&message, callback_game_start, callback_game_stop, callback_info); + bool is_message_valid = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop); + // bool is_message_valid = obus_module::loopNeedy(&message, callback_game_start, callback_game_stop); } void callback_game_start() { @@ -27,7 +27,3 @@ void callback_game_start() { void callback_game_stop() { } - -void callback_info(uint8_t info_id, uint8_t [7]) { - -} From 07fd7ed1c8213b601a6231c61485fa4e9a02f959 Mon Sep 17 00:00:00 2001 From: redfast00 Date: Mon, 1 Feb 2021 17:00:15 +0100 Subject: [PATCH 6/7] Add deadline for loop function so users are forced to call it frequently --- lib/obus_module.cpp | 28 ++++++++++++++----- .../month_day_selector/month_day_selector.ino | 4 +-- .../puzzle_testmodule_date.ino | 4 +-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/obus_module.cpp b/lib/obus_module.cpp index fb1351b..74b9429 100644 --- a/lib/obus_module.cpp +++ b/lib/obus_module.cpp @@ -8,6 +8,8 @@ #define BLINK_DELAY_NORMAL 500 #define BLINK_DELAY_FAST 300 +#define MAX_TIME_BETWEEN_CALLS 100 + // Not used normally #define MCP_INT 2 @@ -21,6 +23,7 @@ namespace obus_module { struct obus_can::module this_module; uint8_t strike_count; bool active; +uint32_t next_loop_call_deadline; // Current LED status struct color { bool red; bool green; }; @@ -81,6 +84,7 @@ void _setLedBlink(struct color color, uint16_t delay) { void _resetState() { strike_count = 0; active = false; + next_loop_call_deadline = 0; if (this_module.type == OBUS_TYPE_PUZZLE || this_module.type == OBUS_TYPE_NEEDY) { pinMode(RED_LED, OUTPUT); @@ -113,21 +117,31 @@ void empty_callback_state(uint32_t time_left, uint8_t strikes, uint8_t max_strik (void)puzzle_modules_solved; } +void blink_error(String message) { + bool blink = false; + while (true) { + digitalWrite(RED_LED, blink); + digitalWrite(GREEN_LED, blink); + blink = !blink; + delay(BLINK_DELAY_NORMAL); + Serial.println(message); + } +} + bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved)) { // TODO this can be more efficient by only enabling error interrupts and // reacting to the interrupt instead of checking if the flag is set in a loop // We will need to fork our CAN library for this, because the needed functions are private. // Also, we can't do this by default, because the INT pin is normally not connected to the board if (obus_can::is_error_condition()) { - bool blink = false; - while (true) { - digitalWrite(RED_LED, blink); - digitalWrite(GREEN_LED, blink); - blink = !blink; - delay(BLINK_DELAY_NORMAL); - } + blink_error(F("E CAN error")); } + if (next_loop_call_deadline != 0 && millis() > next_loop_call_deadline) { + blink_error(F("E missed deadline")); + } + next_loop_call_deadline = millis() + MAX_TIME_BETWEEN_CALLS; + bool received_message = false; if (obus_can::receive(message)) { received_message = true; diff --git a/misc/reverse_engineered_hardware/month_day_selector/month_day_selector.ino b/misc/reverse_engineered_hardware/month_day_selector/month_day_selector.ino index eef29eb..976e01f 100644 --- a/misc/reverse_engineered_hardware/month_day_selector/month_day_selector.ino +++ b/misc/reverse_engineered_hardware/month_day_selector/month_day_selector.ino @@ -18,7 +18,7 @@ uint8_t shiftInFixed(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder) { else value |= digitalRead(dataPin) << (7 - i); digitalWrite(clockPin, HIGH); - delay(1); + delayMicroseconds(3); digitalWrite(clockPin, LOW); } return value; @@ -50,7 +50,7 @@ void loop() // run over and over { // read data in digitalWrite(READ_PIN, HIGH); - delay(200); + delayMicroseconds(3); digitalWrite(READ_PIN, LOW); // shift data bit by bit diff --git a/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino b/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino index 3509a11..c0a5890 100644 --- a/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino +++ b/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino @@ -82,7 +82,7 @@ uint8_t read_value_from_date_module(uint8_t bit_order) { else value |= read_bit << (7 - i); digitalWrite(DATE_CLOCK_PIN, HIGH); - delay(1); + delayMicroseconds(3); digitalWrite(DATE_CLOCK_PIN, LOW); } return value; @@ -90,7 +90,7 @@ uint8_t read_value_from_date_module(uint8_t bit_order) { void read_from_date_module(uint8_t* data_out) { digitalWrite(DATE_READ_PIN, HIGH); - delay(200); + delayMicroseconds(3); digitalWrite(DATE_READ_PIN, LOW); for (int i = 0; i < 4; i++) { From afd3ae67f85514494ce0ab18e78cc52ff0f4f657 Mon Sep 17 00:00:00 2001 From: redfast00 Date: Mon, 1 Feb 2021 17:48:26 +0100 Subject: [PATCH 7/7] Add field for amount of puzzle modules connected --- docs/protocol.txt | 2 +- lib/obus_module.cpp | 7 +- lib/obus_module.h | 4 +- src/controller/controller.ino | 2 +- .../needy_testmodule_buttons.ino | 5 +- .../puzzle_testmodule_buttons.ino | 3 +- .../puzzle_testmodule_date.ino | 131 +++++++++--------- 7 files changed, 79 insertions(+), 75 deletions(-) diff --git a/docs/protocol.txt b/docs/protocol.txt index 74230e8..9ac7f92 100644 --- a/docs/protocol.txt +++ b/docs/protocol.txt @@ -51,7 +51,7 @@ Types for controller: - 2 game start [ X B B B B B B B ] -------- - - - - time left ↓ ↓ reserved + time left ↓ ↓ #puzzle modules #strikes #max strikes - 3 state (every x ms – e.g. in the middle of each second) diff --git a/lib/obus_module.cpp b/lib/obus_module.cpp index 74b9429..84b6202 100644 --- a/lib/obus_module.cpp +++ b/lib/obus_module.cpp @@ -128,7 +128,7 @@ void blink_error(String message) { } } -bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved)) { +bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(uint8_t puzzle_modules), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved)) { // TODO this can be more efficient by only enabling error interrupts and // reacting to the interrupt instead of checking if the flag is set in a loop // We will need to fork our CAN library for this, because the needed functions are private. @@ -150,7 +150,8 @@ bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void case OBUS_MSGTYPE_C_GAMESTART: active = true; _setLed(COLOR_YELLOW); - callback_game_start(); + // The field is named puzzle_modules_solved, but it actually contains the amount of puzzle modules + callback_game_start(message->gamestatus.puzzle_modules_solved); break; case OBUS_MSGTYPE_C_HELLO: _resetState(); @@ -183,7 +184,7 @@ bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void return received_message; } -bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved)) { +bool loopNeedy(obus_can::message* message, void (*callback_game_start)(uint8_t puzzle_modules), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]), void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved)) { // For now this is the same function return loopPuzzle(message, callback_game_start, callback_game_stop, callback_info, callback_state); } diff --git a/lib/obus_module.h b/lib/obus_module.h index 8327df0..0705b00 100644 --- a/lib/obus_module.h +++ b/lib/obus_module.h @@ -15,9 +15,9 @@ void setup(uint8_t type, uint8_t id); void empty_callback_info(uint8_t info_id, uint8_t infomessage[7]); void empty_callback_state(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved); -bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) = empty_callback_state); +bool loopPuzzle(obus_can::message* message, void (*callback_game_start)(uint8_t puzzle_modules), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) = empty_callback_state); -bool loopNeedy(obus_can::message* message, void (*callback_game_start)(), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) = empty_callback_state); +bool loopNeedy(obus_can::message* message, void (*callback_game_start)(uint8_t puzzle_modules), void (*callback_game_stop)(), void (*callback_info)(uint8_t info_id, uint8_t infomessage[7]) = empty_callback_info, void (*callback_state)(uint32_t time_left, uint8_t strikes, uint8_t max_strikes, uint8_t puzzle_modules_solved) = empty_callback_state); bool loopInfo(obus_can::message* message, int (*info_generator)(uint8_t*)); diff --git a/src/controller/controller.ino b/src/controller/controller.ino index 9075e63..ab5a541 100644 --- a/src/controller/controller.ino +++ b/src/controller/controller.ino @@ -190,7 +190,7 @@ void initialize_game() { Serial.println(" Game started"); draw_display(millis(), OBUS_GAME_DURATION_MS); - obus_can::send_c_gamestart(this_module, OBUS_GAME_DURATION_MS, strikes, OBUS_MAX_STRIKES, nr_solved_puzzles); + obus_can::send_c_gamestart(this_module, OBUS_GAME_DURATION_MS, strikes, OBUS_MAX_STRIKES, nr_connected_puzzles); } diff --git a/src/modules/needy_testmodule_buttons/needy_testmodule_buttons.ino b/src/modules/needy_testmodule_buttons/needy_testmodule_buttons.ino index cb1002d..e42a234 100644 --- a/src/modules/needy_testmodule_buttons/needy_testmodule_buttons.ino +++ b/src/modules/needy_testmodule_buttons/needy_testmodule_buttons.ino @@ -58,8 +58,9 @@ void loop() { } } -void callback_game_start() { - +void callback_game_start(uint8_t puzzle_modules_connected) { + // Intentionally emtpy + (void)puzzle_modules_connected; } void callback_game_stop() { diff --git a/src/modules/puzzle_testmodule_buttons/puzzle_testmodule_buttons.ino b/src/modules/puzzle_testmodule_buttons/puzzle_testmodule_buttons.ino index 312e1cc..986417f 100644 --- a/src/modules/puzzle_testmodule_buttons/puzzle_testmodule_buttons.ino +++ b/src/modules/puzzle_testmodule_buttons/puzzle_testmodule_buttons.ino @@ -34,8 +34,9 @@ void loop() { } } -void callback_game_start() { +void callback_game_start(uint8_t puzzle_modules_connected) { // Intentionally emtpy + (void)puzzle_modules_connected; } void callback_game_stop() { diff --git a/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino b/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino index c0a5890..66e9b75 100644 --- a/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino +++ b/src/modules/puzzle_testmodule_date/puzzle_testmodule_date.ino @@ -27,104 +27,105 @@ uint8_t correct_code[4] = { - DATE_MODE_STOP, - 12, - 34, - 56 + DATE_MODE_STOP, + 12, + 34, + 56 }; ezButton solve_button(DATE_SOLVE_BTN); void setup() { - Serial.begin(115200); - obus_module::setup(OBUS_TYPE_PUZZLE, 123); - solve_button.setDebounceTime(10); - solve_button.setCountMode(COUNT_RISING); - setup_date_module(); + Serial.begin(115200); + obus_module::setup(OBUS_TYPE_PUZZLE, 123); + solve_button.setDebounceTime(10); + solve_button.setCountMode(COUNT_RISING); + setup_date_module(); } obus_can::message message; void loop() { - bool received = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop); - // TODO handle update frames (not needed for this module, but could be useful as example code) - solve_button.loop(); - if (solve_button.getCount() > 0) { - uint8_t data[4]; - read_from_date_module(data); + bool received = obus_module::loopPuzzle(&message, callback_game_start, callback_game_stop); + // TODO handle update frames (not needed for this module, but could be useful as example code) + solve_button.loop(); + if (solve_button.getCount() > 0) { + uint8_t data[4]; + read_from_date_module(data); - if (check_date_code(data)) { - Serial.println("SOLVED!"); - obus_module::solve(); - } else { - Serial.println("STRIKE!"); - obus_module::strike(); - } - solve_button.resetCount(); - } + if (check_date_code(data)) { + Serial.println("SOLVED!"); + obus_module::solve(); + } else { + Serial.println("STRIKE!"); + obus_module::strike(); + } + solve_button.resetCount(); + } } void setup_date_module() { - pinMode(DATE_CLOCK_PIN, OUTPUT); - pinMode(DATE_DATA_PIN, INPUT); - pinMode(DATE_READ_PIN, OUTPUT); + pinMode(DATE_CLOCK_PIN, OUTPUT); + pinMode(DATE_DATA_PIN, INPUT); + pinMode(DATE_READ_PIN, OUTPUT); } uint8_t read_value_from_date_module(uint8_t bit_order) { - digitalWrite(DATE_CLOCK_PIN, LOW); - uint8_t value = 0; - for (int i = 0; i < 8; i++) { - uint8_t read_bit = digitalRead(DATE_DATA_PIN); - if (bit_order == LSBFIRST) - value |= read_bit << i; - else - value |= read_bit << (7 - i); - digitalWrite(DATE_CLOCK_PIN, HIGH); - delayMicroseconds(3); - digitalWrite(DATE_CLOCK_PIN, LOW); - } - return value; + digitalWrite(DATE_CLOCK_PIN, LOW); + uint8_t value = 0; + for (int i = 0; i < 8; i++) { + uint8_t read_bit = digitalRead(DATE_DATA_PIN); + if (bit_order == LSBFIRST) + value |= read_bit << i; + else + value |= read_bit << (7 - i); + digitalWrite(DATE_CLOCK_PIN, HIGH); + delayMicroseconds(3); + digitalWrite(DATE_CLOCK_PIN, LOW); + } + return value; } void read_from_date_module(uint8_t* data_out) { - digitalWrite(DATE_READ_PIN, HIGH); - delayMicroseconds(3); - digitalWrite(DATE_READ_PIN, LOW); + digitalWrite(DATE_READ_PIN, HIGH); + delayMicroseconds(3); + digitalWrite(DATE_READ_PIN, LOW); - for (int i = 0; i < 4; i++) { - data_out[i] = read_value_from_date_module(LSBFIRST); - } + for (int i = 0; i < 4; i++) { + data_out[i] = read_value_from_date_module(LSBFIRST); + } - for (int i = 1; i < 4; i++) { - // Convert raw data to human interpretable number - data_out[i] = 10*(data_out[i] & 0x0F) + ((data_out[i] & 0xF0) >> 4); - } + for (int i = 1; i < 4; i++) { + // Convert raw data to human interpretable number + data_out[i] = 10*(data_out[i] & 0x0F) + ((data_out[i] & 0xF0) >> 4); + } - //for (int i = 0; i < 4; i++) { - // Serial.print(data_out[i]); - // Serial.print(" "); - //} + //for (int i = 0; i < 4; i++) { + // Serial.print(data_out[i]); + // Serial.print(" "); + //} - //Serial.println(); - digitalWrite(DATE_CLOCK_PIN, LOW); + //Serial.println(); + digitalWrite(DATE_CLOCK_PIN, LOW); } bool check_date_code(uint8_t* code) { - for (int i = 0; i < 4; i++) { - if (code[i] != correct_code[i]) { - return false; - } - } - return true; + for (int i = 0; i < 4; i++) { + if (code[i] != correct_code[i]) { + return false; + } + } + return true; } -void callback_game_start() { - // Intentionally emtpy +void callback_game_start(uint8_t puzzle_modules_connected) { + // Intentionally emtpy + (void)puzzle_modules_connected; } void callback_game_stop() { - // Intentionally empty + // Intentionally empty }