commit
26df06e55f
10 changed files with 232 additions and 9 deletions
|
@ -7,7 +7,9 @@ You see an armed time bomb but don't know how to disarm it. Your friends found a
|
|||
1. [Install](https://www.arduino.cc/en/Guide/#install-the-arduino-desktop-ide) the Arduino IDE.
|
||||
2. Clone this repository with Git in a permanent location on your drive.
|
||||
3. Symlink the library: `ln -s /ABSOLUTE/PATH/TO/REPO/lib /PATH/TO/Arduino/libraries/obus`
|
||||
4. TODO
|
||||
(on most Linux distro's, this the Arduino folder is in `$HOME/Arduino`)
|
||||
4. Follow [these steps](https://github.com/autowp/arduino-mcp2515/#software-usage) to install the CAN library
|
||||
5. Execute `./src/new_module.sh` to create a new module
|
||||
|
||||
# Background
|
||||
## Game
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
|
||||
#include "obus_can.h"
|
||||
|
||||
// Chip select for the CAN module
|
||||
#define MCP_CS 8
|
||||
|
||||
namespace obus_can {
|
||||
|
||||
MCP2515 mcp2515(10);
|
||||
MCP2515 mcp2515(MCP_CS);
|
||||
bool is_init = false;
|
||||
|
||||
|
||||
|
@ -136,6 +139,9 @@ bool receive(struct message *msg) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool is_error_condition() {
|
||||
return mcp2515.getInterrupts() & MCP2515::CANINTF_ERRIF;
|
||||
}
|
||||
|
||||
void send(struct message *msg) {
|
||||
if (!is_init) {
|
||||
|
|
|
@ -77,7 +77,7 @@ void init();
|
|||
/**
|
||||
* Receive a message
|
||||
*
|
||||
* @param msg Pointer to memory where the received message will be wriitten
|
||||
* @param msg Pointer to memory where the received message will be written
|
||||
* @return true if a message was received, false otherwise
|
||||
*/
|
||||
bool receive(struct message *msg);
|
||||
|
@ -90,6 +90,8 @@ bool receive(struct message *msg);
|
|||
*/
|
||||
void send(struct message *msg);
|
||||
|
||||
bool is_error_condition();
|
||||
|
||||
|
||||
/**
|
||||
* For internal use only
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
#include "obus_can.h"
|
||||
#include "obus_module.h"
|
||||
|
||||
#define RED_LED A4
|
||||
#define GREEN_LED A5
|
||||
|
||||
#define MCP_INT 2
|
||||
|
||||
namespace obus_module {
|
||||
|
||||
|
||||
struct obus_can::module this_module;
|
||||
uint8_t strike_count;
|
||||
|
||||
bool active;
|
||||
uint32_t time_stop_strike_led;
|
||||
|
||||
void setup(uint8_t type, uint8_t id) {
|
||||
this_module.type = type;
|
||||
|
@ -14,19 +21,83 @@ void setup(uint8_t type, uint8_t id) {
|
|||
obus_can::init();
|
||||
|
||||
strike_count = 0;
|
||||
active = false;
|
||||
pinMode(RED_LED, OUTPUT);
|
||||
pinMode(GREEN_LED, OUTPUT);
|
||||
digitalWrite(RED_LED, LOW);
|
||||
digitalWrite(GREEN_LED, LOW);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
bool loopPuzzle(obus_can::message* message) {
|
||||
// Check if we need to turn the red "strike" LED back off after
|
||||
// turning it on because of a strike
|
||||
if (time_stop_strike_led && time_stop_strike_led > millis()) {
|
||||
digitalWrite(RED_LED, LOW);
|
||||
time_stop_strike_led = 0;
|
||||
}
|
||||
// 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
|
||||
if (obus_can::is_error_condition()) {
|
||||
bool blink = false;
|
||||
while (true) {
|
||||
digitalWrite(RED_LED, blink);
|
||||
digitalWrite(GREEN_LED, blink);
|
||||
blink = !blink;
|
||||
delay(500);
|
||||
}
|
||||
}
|
||||
if (obus_can::receive(message)) {
|
||||
switch(message->msg_type) {
|
||||
case OBUS_MSGTYPE_C_GAMESTART:
|
||||
active = true;
|
||||
callback_game_start();
|
||||
break;
|
||||
case OBUS_MSGTYPE_C_HELLO:
|
||||
obus_can::send_m_hello(this_module);
|
||||
break;
|
||||
case OBUS_MSGTYPE_C_SOLVED:
|
||||
case OBUS_MSGTYPE_C_TIMEOUT:
|
||||
case OBUS_MSGTYPE_C_STRIKEOUT:
|
||||
active = false;
|
||||
callback_game_stop();
|
||||
break;
|
||||
case OBUS_MSGTYPE_C_ACK:
|
||||
break;
|
||||
case OBUS_MSGTYPE_C_STATE:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool loopNeedy(obus_can::message* message) {
|
||||
// For now this is the same function
|
||||
return loopPuzzle(message);
|
||||
}
|
||||
|
||||
void strike() {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
strike_count++;
|
||||
digitalWrite(RED_LED, HIGH);
|
||||
time_stop_strike_led = millis() + 1000;
|
||||
obus_can::send_m_strike(this_module, strike_count);
|
||||
}
|
||||
|
||||
void solve() {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
obus_can::send_m_solved(this_module);
|
||||
digitalWrite(GREEN_LED, HIGH);
|
||||
active = false;
|
||||
}
|
||||
|
||||
bool is_active() {
|
||||
return active;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,16 +4,24 @@
|
|||
#include "Arduino.h"
|
||||
#include <obus_can.h>
|
||||
|
||||
void callback_game_start();
|
||||
|
||||
void callback_game_stop();
|
||||
|
||||
namespace obus_module {
|
||||
|
||||
void setup(uint8_t type, uint8_t id);
|
||||
|
||||
void loop();
|
||||
bool loopPuzzle(obus_can::message* message);
|
||||
|
||||
bool loopNeedy(obus_can::message* message);
|
||||
|
||||
void strike();
|
||||
|
||||
void solve();
|
||||
|
||||
bool is_active();
|
||||
|
||||
}
|
||||
|
||||
#endif /* end of include guard: OBUS_MODULE_H */
|
||||
|
|
6
src/modules/testmodule_buttons/doc/index.md
Normal file
6
src/modules/testmodule_buttons/doc/index.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
## Testmodule buttons
|
||||
|
||||
Don't press the red button. Press the green button to solve the module.
|
||||
|
||||
### Credits
|
||||
Module developed by redfast00.
|
44
src/modules/testmodule_buttons/testmodule_buttons.ino
Normal file
44
src/modules/testmodule_buttons/testmodule_buttons.ino
Normal file
|
@ -0,0 +1,44 @@
|
|||
// (c) 2020, redfast00
|
||||
// See the LICENSE file for conditions for copying
|
||||
|
||||
#include <obus_module.h>
|
||||
#include <ezButton.h>
|
||||
|
||||
ezButton red_button(5);
|
||||
ezButton green_button(6);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
// WARNING: do not use 255 for your module
|
||||
obus_module::setup(OBUS_TYPE_PUZZLE, 255);
|
||||
red_button.setDebounceTime(100);
|
||||
green_button.setDebounceTime(100);
|
||||
}
|
||||
|
||||
obus_can::message message;
|
||||
|
||||
void loop() {
|
||||
bool received = obus_module::loopPuzzle(&message);
|
||||
// TODO handle update frames (not needed for this module, but could be useful as example code)
|
||||
|
||||
red_button.loop();
|
||||
green_button.loop();
|
||||
|
||||
if (red_button.getCount() > 0) {
|
||||
red_button.resetCount();
|
||||
obus_module::strike();
|
||||
}
|
||||
|
||||
if (green_button.getCount() > 0) {
|
||||
green_button.resetCount();
|
||||
obus_module::solve();
|
||||
}
|
||||
}
|
||||
|
||||
void callback_game_start() {
|
||||
// Intentionally emtpy
|
||||
}
|
||||
|
||||
void callback_game_stop() {
|
||||
// Intentionally empty
|
||||
}
|
6
src/modules/testmodule_needy_buttons/doc/index.md
Normal file
6
src/modules/testmodule_needy_buttons/doc/index.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
## Testmodule needy buttons
|
||||
|
||||
If the module starts making a sound, press the button.
|
||||
|
||||
### Credits
|
||||
Module developed by redfast00.
|
|
@ -0,0 +1,68 @@
|
|||
// (c) 2020, redfast00
|
||||
// See the LICENSE file for conditions for copying
|
||||
|
||||
#include <obus_module.h>
|
||||
#include <ezButton.h>
|
||||
|
||||
#define SPEAKER_PIN 10
|
||||
|
||||
ezButton green_button(6);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
// WARNING: do not use 255 for your module
|
||||
obus_module::setup(OBUS_TYPE_NEEDY, 255);
|
||||
green_button.setDebounceTime(100);
|
||||
}
|
||||
|
||||
obus_can::message message;
|
||||
|
||||
uint32_t next_activation_time = 0;
|
||||
uint32_t trigger_time = 0;
|
||||
|
||||
void loop() {
|
||||
bool is_message_valid = obus_module::loopNeedy(&message);
|
||||
green_button.loop();
|
||||
|
||||
// Every second, have a 1/20 chance to trigger the countdown
|
||||
if (obus_module::is_active() && !trigger_time && (millis() > next_activation_time)) {
|
||||
next_activation_time = millis() + 1000;
|
||||
if (random(20) == 0) {
|
||||
trigger_time = millis() + 30000;
|
||||
}
|
||||
}
|
||||
|
||||
// Strike if time runs out
|
||||
if (trigger_time && millis() > trigger_time) {
|
||||
obus_module::strike();
|
||||
trigger_time = 0;
|
||||
}
|
||||
|
||||
// If the button is pressed, reset countdown if countdown is running, else strike
|
||||
if (green_button.getCount() > 0) {
|
||||
green_button.resetCount();
|
||||
if (trigger_time) {
|
||||
trigger_time = 0;
|
||||
} else {
|
||||
obus_module::strike();
|
||||
}
|
||||
}
|
||||
|
||||
// Play the appropriate sound
|
||||
if (trigger_time && millis() > trigger_time - 15000) {
|
||||
tone(SPEAKER_PIN, 440);
|
||||
}
|
||||
else if (trigger_time) {
|
||||
tone(SPEAKER_PIN, 449);
|
||||
} else {
|
||||
noTone(SPEAKER_PIN);
|
||||
}
|
||||
}
|
||||
|
||||
void callback_game_start() {
|
||||
|
||||
}
|
||||
|
||||
void callback_game_stop() {
|
||||
|
||||
}
|
|
@ -4,16 +4,26 @@
|
|||
#include <obus_module.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
Serial.begin(115200);
|
||||
|
||||
// Choose one
|
||||
// Puzzle: a module that must be solved
|
||||
obus_module::setup(OBUS_TYPE_PUZZLE, /* Retrieve ID from MOANA */);
|
||||
// Needy: a module that periodically requires an action not to get strikes
|
||||
// obusmodule_init(OBUS_TYPE_NEEDY, /* Retrieve ID from MOANA */);
|
||||
// obus_module::setup(OBUS_TYPE_NEEDY, /* Retrieve ID from MOANA */);
|
||||
}
|
||||
|
||||
obus_can::message message;
|
||||
|
||||
void loop() {
|
||||
obus_module::loop();
|
||||
bool is_message_valid = obus_module::loop_puzzle(&message);
|
||||
// bool bool is_message_valid = obus_module::loop_needy(&message);
|
||||
}
|
||||
|
||||
void callback_game_start() {
|
||||
|
||||
}
|
||||
|
||||
void callback_game_stop() {
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue