aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomasintAnker <thomasintanker1@gmail.com>2024-06-24 14:59:56 +0200
committerThomasintAnker <thomasintanker1@gmail.com>2024-06-24 14:59:56 +0200
commita0c664908b9112306c5858ccb106d1a0e5555df7 (patch)
tree8ca77d1210d1683a97f4da131c6ffac8123d4375
parent381149dd7a1f4d5f48dd5ac07186c73371ff3c04 (diff)
parentec7f5e970ed03acb33eb5dc3b67f3d52af52e6dc (diff)
merge main into wip/mc
-rw-r--r--.clang-format12
-rw-r--r--.clang-tidy7
-rw-r--r--.editorconfig2
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules2
-rw-r--r--Doxyfile33
-rw-r--r--client/cmd.cpp2
-rw-r--r--client/cmd.h55
-rw-r--r--client/i2c.cpp4
-rw-r--r--client/i2c.h29
-rw-r--r--client/parse.h14
-rw-r--r--client/readme.md32
-rw-r--r--client/rl.cpp17
-rw-r--r--client/rl.h43
-rw-r--r--client/sock.cpp2
-rw-r--r--client/sock.h43
-rw-r--r--client/xxd.h9
-rw-r--r--docs/.gitignore1
-rw-r--r--docs/design.adoc479
-rw-r--r--docs/doxygen-layout.xml62
-rw-r--r--docs/fat.adoc289
-rw-r--r--docs/figs.drawio452
-rw-r--r--docs/handover.adoc313
-rw-r--r--docs/img/.gitignore3
-rw-r--r--docs/img/main-controller-state.svg2
-rw-r--r--docs/img/main-controller-top.svg2
-rw-r--r--docs/img/power-supply-top.svg2
-rw-r--r--docs/img/puzzle-module-common-state.svg2
-rw-r--r--docs/img/puzzle-module-top.svg2
-rw-r--r--docs/img/sequence-puzzle-module-init.puml17
-rw-r--r--docs/img/sequence-puzzle-module-init.svg3
-rw-r--r--docs/img/software-components.puml37
-rw-r--r--docs/img/style.ipuml4
-rw-r--r--docs/img/system-bus.svg2
-rw-r--r--docs/img/system-top.svg2
-rw-r--r--docs/makefile6
-rw-r--r--docs/reqs.adoc45
-rw-r--r--docs/research.adoc201
-rw-r--r--docs/share/refs.bib62
-rw-r--r--docs/theme.yml8
m---------lib/Arduino-CMake-Toolchain0
-rw-r--r--lib/i2ctcp/i2ctcpv1.h66
-rw-r--r--lib/i2ctcp/readme.md25
-rw-r--r--lib/mpack/mpack.h31
-rw-r--r--lib/pbdrv/CMakeLists.txt6
-rw-r--r--lib/pbdrv/drv/arduino/include.cmake2
-rw-r--r--lib/pbdrv/drv/arduino/index.dox25
-rw-r--r--lib/pbdrv/drv/arduino/mod.cpp37
-rw-r--r--lib/pbdrv/drv/index.dox19
-rw-r--r--lib/pbdrv/drv/rp2040/include.cmake11
-rw-r--r--lib/pbdrv/drv/rp2040/index.dox31
-rw-r--r--lib/pbdrv/drv/rp2040/mod.c49
-rw-r--r--lib/pbdrv/drv/rp2040/pb-mod.h21
-rw-r--r--lib/pbdrv/ext/freertos/include.cmake4
-rw-r--r--lib/pbdrv/ext/freertos/index.dox6
-rw-r--r--lib/pbdrv/ext/freertos/pb-mem.c5
-rw-r--r--lib/pbdrv/ext/freertos/pb-mod.c9
-rw-r--r--lib/pbdrv/ext/index.dox24
-rw-r--r--lib/pbdrv/ext/stdlib/index.dox6
-rw-r--r--lib/pbdrv/ext/stdlib/pb-mem.c5
-rw-r--r--lib/pbdrv/index.dox73
-rw-r--r--lib/pbdrv/pb-buf.h20
-rw-r--r--lib/pbdrv/pb-mem.h55
-rw-r--r--lib/pbdrv/pb-mod.h96
-rw-r--r--lib/pbdrv/pb-msg.h43
-rw-r--r--lib/pbdrv/pb-route.c23
-rw-r--r--lib/pbdrv/pb-route.h175
-rw-r--r--lib/pbdrv/pb-send.c14
-rw-r--r--lib/pbdrv/pb-send.h117
-rw-r--r--lib/pbdrv/pb-serial.h76
-rw-r--r--lib/pbdrv/pb-types.h118
-rw-r--r--lib/pbdrv/pb.h28
-rw-r--r--lib/pbdrv/spec.adoc133
-rw-r--r--main/CMakeLists.txt4
-rw-r--r--main/blink.h12
-rw-r--r--main/config.def.h95
-rw-r--r--main/i2c.c35
-rw-r--r--main/i2c.h15
-rw-r--r--main/index.dox13
-rw-r--r--main/init.c14
-rw-r--r--main/init.h12
-rw-r--r--main/mod.c3
-rw-r--r--main/pbdrv.c95
-rw-r--r--main/pbdrv.h52
-rw-r--r--main/readme.md15
-rw-r--r--main/sock.h15
-rw-r--r--main/tasks.h9
-rw-r--r--makefile13
-rw-r--r--puzzle/dummy/CMakeLists.txt14
-rw-r--r--puzzle/dummy/FreeRTOSConfig.h4
-rw-r--r--puzzle/dummy/index.dox9
-rw-r--r--puzzle/dummy/makefile16
-rw-r--r--puzzle/neo/CMakeLists.txt44
-rw-r--r--puzzle/neo/FreeRTOSConfig.h52
-rw-r--r--puzzle/neo/console-neopuzzle/neo.cpp100
-rw-r--r--puzzle/neo/index.dox14
l---------puzzle/neo/lib1
-rw-r--r--puzzle/neo/main.cpp (renamed from puzzle/neo/arduino-neopuzzle/arduino-neopuzzle.ino)79
-rw-r--r--puzzle/neo/makefile8
-rw-r--r--puzzle/neo/mod.c6
-rw-r--r--puzzle/readme.md22
-rw-r--r--puzzle/vault/CMakeLists.txt41
-rw-r--r--puzzle/vault/FreeRTOSConfig.h52
-rw-r--r--puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino150
-rw-r--r--puzzle/vault/console-vaultpuzzle/vault.cpp130
-rw-r--r--puzzle/vault/index.dox11
l---------puzzle/vault/lib1
-rw-r--r--puzzle/vault/main.cpp187
-rw-r--r--puzzle/vault/makefile8
-rw-r--r--puzzle/vault/mod.c6
-rw-r--r--readme.md69
111 files changed, 3256 insertions, 1826 deletions
diff --git a/.clang-format b/.clang-format
index 3266955..064fa96 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,11 +1,10 @@
---
AccessModifierOffset: -4
-AlignConsecutiveAssignments: true
AllowShortIfStatementsOnASingleLine: AllIfsAndElse
AllowShortLoopsOnASingleLine: true
BasedOnStyle: LLVM
BreakBeforeBraces: Attach
-ColumnLimit: 180
+ColumnLimit: 80
EmptyLineBeforeAccessModifier: Always
IndentAccessModifiers: false
IndentCaseLabels: true
@@ -14,6 +13,13 @@ Language: Cpp
Standard: Cpp11
TabWidth: 4
UseTab: Always
+PointerAlignment: Middle
+SpaceAfterCStyleCast: true
+AlignConsecutiveAssignments:
+ Enabled: false
+AlignTrailingComments:
+ Kind: Leave
+ReflowComments: false
...
-# vim: ft=yaml \ No newline at end of file
+# vim: ft=yaml
diff --git a/.clang-tidy b/.clang-tidy
index 7a8470a..b242e3f 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,25 +1,18 @@
Checks: '-*,readability-identifier-naming'
CheckOptions:
- { key: readability-identifier-naming.EnumCase, value: lower_case }
- - { key: readability-identifier-naming.EnumPrefix, value: hh_e_ }
- { key: readability-identifier-naming.GlobalFunctionCase, value: lower_case }
- - { key: readability-identifier-naming.GlobalFunctionPrefix, value: hh_ }
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
- - { key: readability-identifier-naming.ClassPrefix, value: hh }
- { key: readability-identifier-naming.ClassMethodCase, value: lower_case }
- { key: readability-identifier-naming.ClassMethodPrefix, value: '' }
- { key: readability-identifier-naming.ClassMemberCase, value: lower_case }
- { key: readability-identifier-naming.ClassMemberPrefix, value: '' }
- { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }
- { key: readability-identifier-naming.GlobalConstantIgnoredRegexp, value: _.* }
- - { key: readability-identifier-naming.GlobalConstantPrefix, value: HH_ }
- { key: readability-identifier-naming.GlobalVariableCase, value: lower_case }
- { key: readability-identifier-naming.GlobalVariableIgnoredRegexp, value: _.* }
- - { key: readability-identifier-naming.GlobalVariablePrefix, value: g_hh_ }
- { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE }
- { key: readability-identifier-naming.MacroDefinitionIgnoredRegexp, value: _.* }
- - { key: readability-identifier-naming.MacroDefinitionPrefix, value: HH_ }
- { key: readability-identifier-naming.StructCase, value: lower_case }
- - { key: readability-identifier-naming.StructPrefix, value: hh_s_ }
# vim: ft=yaml
diff --git a/.editorconfig b/.editorconfig
index cd37156..bd1f474 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,7 +5,7 @@ indent_style = tab
end_of_line = lf
insert_final_newline = true
-[*.md]
+[*.{md,yml}]
indent_style = space
indent_size = 2
diff --git a/.gitignore b/.gitignore
index 19dc4f4..6064624 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
build
.vscode/**
.cache
+doxygen
diff --git a/.gitmodules b/.gitmodules
index 9ff7e96..37a53dd 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -21,6 +21,6 @@
[submodule "lib/Arduino-CMake-Toolchain"]
path = lib/Arduino-CMake-Toolchain
url = https://github.com/a9183756-gh/Arduino-CMake-Toolchain
- branch = e745a9bed3c3fb83442d55bf05630f31574674f2
+ branch = release-1.1-dev
shallow = true
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..3dd7951
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,33 @@
+# Doxyfile 1.11.0
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = "puzzlebox"
+OUTPUT_DIRECTORY = doxygen
+LAYOUT_FILE = docs/doxygen-layout.xml
+
+INPUT += readme.md
+INPUT += lib/mpack
+INPUT += lib/i2ctcp
+INPUT += lib/pbdrv
+INPUT += client
+INPUT += main
+INPUT += puzzle
+
+EXCLUDE = lib/mpack/src
+EXCLUDE_PATTERNS = **/build
+EXCLUDE_SYMLINKS = YES
+
+FILE_PATTERNS = *.c *.cpp *.h *.hpp *.md *.dox
+RECURSIVE = YES
+
+GENERATE_LATEX = NO
+
+ALIASES += I2C="I&sup2;C"
+INPUT_FILTER = "sed -e 's/\<I2C\>\|\<I<sup>2<\/sup>C\>/\\I2C/g'"
+
+USE_MDFILE_AS_MAINPAGE = readme.md
+HTML_INDEX_NUM_ENTRIES = 1 # collapse trees by default
+REPEAT_BRIEF = NO
+
+INTERNAL_DOCS = YES
+EXTRACT_STATIC = YES
+
diff --git a/client/cmd.cpp b/client/cmd.cpp
index 10d53e3..062fefa 100644
--- a/client/cmd.cpp
+++ b/client/cmd.cpp
@@ -28,7 +28,7 @@ void cmd_test(char*) {
void cmd_help(char*) {
printf("List of available commands:\n");
for (size_t i = 0; i < cmds_length; i++) {
- struct cmd cmd = cmds[i];
+ cmd_t cmd = cmds[i];
printf(" %-*s", 10, cmd.name);
if (cmd.info != NULL)
printf(" %s", cmd.info);
diff --git a/client/cmd.h b/client/cmd.h
index 961ef89..4f77d50 100644
--- a/client/cmd.h
+++ b/client/cmd.h
@@ -1,17 +1,49 @@
#pragma once
+/**
+ * \ingroup pbc
+ * \defgroup pbc_cmd Commands
+ * \brief Commands within \ref pbc
+ *
+ * \note A manpage is available containing end-user usage instructions inside
+ * the \ref client folder in the source code repository. This page contains the
+ * internal code documentation for the commands defined in \c pbc.
+ *
+ * \{
+ */
+
#include <stddef.h>
-typedef void cmd_handle_t(char *);
-typedef char** cmd_complete_t(const char*, int, int);
+/**
+ * \internal
+ * \brief Command handler function
+ *
+ * \param line Remaining text after command name on command line
+ */
+typedef void cmd_handle_t(char * line);
+/**
+ * \internal
+ * \brief Command completion function
+ *
+ * \param text Current word to complete
+ * \param start Index in \c rl_line_buffer of cursor position
+ * \param end End index of \p text in \c rl_line_buffer
+ *
+ * \return Array of \c char* with suggestions. The array is terminated by a
+ * NULL pointer.
+ */
+typedef char** cmd_complete_t(const char* text, int start, int end);
-struct cmd {
- cmd_handle_t * handle;
- const char* name;
- const char* info;
- cmd_complete_t * complete;
-};
-typedef struct cmd cmd_t;
+/**
+ * \internal
+ * \brief Command definition struct
+ */
+typedef struct {
+ cmd_handle_t * handle; //!< Handler function (required)
+ const char* name; //!< Command name (required)
+ const char* info; //!< Command info (shown in help command) (optional = NULL)
+ cmd_complete_t * complete; //!< Completion function (optional = NULL)
+} cmd_t;
cmd_handle_t cmd_exit;
cmd_handle_t cmd_test;
@@ -23,6 +55,7 @@ cmd_handle_t cmd_skip;
cmd_handle_t cmd_dump;
cmd_complete_t cmd_dump_complete;
+//! Commands
static const cmd_t cmds[] = {
{
.handle = cmd_exit,
@@ -68,5 +101,9 @@ static const cmd_t cmds[] = {
},
#endif
};
+
+//! Number of commands defined in \c cmds
static const size_t cmds_length = sizeof(cmds) / sizeof(cmds[0]);
+/// \}
+
diff --git a/client/i2c.cpp b/client/i2c.cpp
index 78e5585..3655191 100644
--- a/client/i2c.cpp
+++ b/client/i2c.cpp
@@ -35,9 +35,9 @@ void i2c_send(uint16_t addr, const char * data, size_t data_size) {
static void i2c_handle_cmd_read(uint16_t, const char *, size_t);
-void i2c_recv(uint16_t addr, const char * data, size_t data_size) {
+void i2c_recv(const char * data, size_t data_size) {
if (i2c_dump_recv) {
- printf("[%s] addr(0x%02x) data(0x%02lx):\n", __FUNCTION__, addr, data_size);
+ printf("[%s] data(0x%02lx):\n", __FUNCTION__, data_size);
xxd(data, data_size);
}
}
diff --git a/client/i2c.h b/client/i2c.h
index f9f58f9..d2cfa9a 100644
--- a/client/i2c.h
+++ b/client/i2c.h
@@ -3,6 +3,33 @@
#include <stdint.h>
#include <stddef.h>
+/**
+ * \ingroup pbc
+ * \defgroup pbc_i2c I2C
+ * \brief I2C abstraction functions
+ * \{
+ */
+
+/**
+ * \brief Fake I2C send function
+ *
+ * This function sends an I2C message to the main controller over TCP using
+ * \ref i2ctcp.
+ *
+ * \param addr I2C address
+ * \param data Data to send
+ * \param data_size size of \p data
+ */
void i2c_send(uint16_t addr, const char * data, size_t data_size);
-void i2c_recv(uint16_t addr, const char * data, size_t data_size);
+/**
+ * \brief Fake I2C receive handler
+ *
+ * This function is called for I2C messages received by the main controller and
+ * forwarded to \ref pbc.
+ *
+ * \param data Received data
+ * \param data_size size of \p data
+ */
+void i2c_recv(const char * data, size_t data_size);
+/// \}
diff --git a/client/parse.h b/client/parse.h
index 94afe70..1beb714 100644
--- a/client/parse.h
+++ b/client/parse.h
@@ -2,11 +2,23 @@
#include <stddef.h>
+/**
+ * \ingroup pbc
+ * \defgroup pbc_parse Parse
+ * \brief Debug \c send command parser utilities
+ * \{
+ */
+
+//! Internal field separator (i.e. whitespace delimiter)
#define IFS " \t\n"
+//! Octal digit character set
#define SET_OCT "01234567"
+//! Decimal digit character set
#define SET_DEC "0123456789"
+//! Hexadecimal digit character set
#define SET_HEX SET_DEC"abcdefABCDEF"
+//! (Hexadecimal) byte string character set
#define SET_HEX_STR SET_HEX":"
/**
@@ -40,3 +52,5 @@ char* consume_token(char * token, const char * ifs);
*/
int strtodata(const char * str, char ** data, size_t * size);
+/// \}
+
diff --git a/client/readme.md b/client/readme.md
index fcde40d..b9e0b09 100644
--- a/client/readme.md
+++ b/client/readme.md
@@ -1,3 +1,6 @@
+\defgroup pbc pbc
+\brief Puzzle box client
+
# puzzle box client
This folder contains the source code for the puzzle box client (pbc). This is a
@@ -7,30 +10,21 @@ game operator to control and monitor the state of a puzzle box, but is also a
useful debugging tool when developing puzzle modules, as it allows you to send
arbitrary data over the puzzle bus.
-## WIP TODO
-
-- cleanup
- - separate ../shared/pb/moddrv.c into a puzzle module specific and 'common' bit
- - use the common bit in i2c.cpp instead
- - cast to structs in ../shared/pb/moddrv.c
-- functionality
- - print pretty tree of connected puzzle modules
- - add enum to string functions in CLIENT ONLY
-
## Features
- List detected puzzle modules
- Reset puzzle modules (individually or all to reset the box)
- Skip puzzle modules (individually or all)
- Request puzzle box state
-
-Debug only:
-- Send arbitrary messages
+- Debug: send arbitrary messages
## Building
-PBC is a standard CMake project, but a [makefile](./makefile) is provided for
-convenience (still requires CMake and Ninja are installed).
+PBC is a standard CMake project.
+
+## Using
+
+See ./pbc.1 for usage.
## Send data
@@ -45,8 +39,10 @@ send 0x39 68:65:6c:6c:6f 44 0x20 'world' 33
The data is concatenated, and may contain mixed types of literals
-## known bugs (TODO)
-- tab completion for `dump` seems to print garbage sometimes
-- the send command with an address but no data causes a segmentation fault
+## WIP TODO
+
+- add enum to string functions in CLIENT ONLY
+- bug: tab completion for `dump` seems to print garbage sometimes
+- bug: the send command with an address but no data causes a segmentation fault
diff --git a/client/rl.cpp b/client/rl.cpp
index fa44bf4..2e74e5f 100644
--- a/client/rl.cpp
+++ b/client/rl.cpp
@@ -57,7 +57,7 @@ static char* rl_completion_entries(const char *text, int state) {
if (state == 0) i = 0;
while (i < cmds_length) {
- struct cmd cmd = cmds[i];
+ cmd_t cmd = cmds[i];
i++;
if (strncmp(text, cmd.name, strlen(text)) == 0) {
return strdup(cmd.name);
@@ -119,24 +119,25 @@ int rl_word(const char * line, int cursor) {
return word;
}
+/// \internal
typedef struct {
const char * word;
- const char ** suggestions;
+ const char ** options;
} __rl_complete_list_data_t;
-char** rl_complete_list(const char * word, const char ** suggestions) {
+char** rl_complete_list(const char * word, const char ** options) {
__rl_complete_list_data_t data = {
.word = word,
- .suggestions = suggestions,
+ .options = options,
};
return rl_completion_matches((char *) &data, [](const char * text, int state) -> char * {
__rl_complete_list_data_t data = *(__rl_complete_list_data_t *) text;
static size_t i = 0;
if (state == 0) i = 0;
- while (data.suggestions[i] != NULL) {
- const char * suggestion = data.suggestions[i++];
- if (strncmp(data.word, suggestion, strlen(data.word)) == 0)
- return strdup(suggestion);
+ while (data.options[i] != NULL) {
+ const char * option = data.options[i++];
+ if (strncmp(data.word, option, strlen(data.word)) == 0)
+ return strdup(option);
}
return NULL;
});
diff --git a/client/rl.h b/client/rl.h
index ab31ddb..d2f8612 100644
--- a/client/rl.h
+++ b/client/rl.h
@@ -1,12 +1,53 @@
#pragma once
+/**
+ * \ingroup pbc
+ * \defgroup pbc_rl rl
+ * \brief GNU Readline related functions
+ * \{
+ */
+
+//! Reset color (ANSI sequence)
#define COLOR_OFF "\x1b[0m"
+//! Set font to bold (ANSI sequence)
#define COLOR_BOLD "\x1b[1m"
+//! Prompt text
#define CLI_PROMPT "(" COLOR_BOLD "pbc" COLOR_OFF ") "
+//! CLI entrypoint
int cli_main();
+
+/**
+ * \brief Print format string to stdout without disturbing the readline prompt
+ *
+ * This function saves and restores the current readline prompt before/after
+ * calling printf. This function is not required for commands that print output
+ * synchronously, as the prompt is only shown after a command handler
+ * completes.
+ */
void rl_printf(const char * fmt, ...);
+/**
+ * \brief Get the index of the word currently under the cursor
+ *
+ * \param line Command line contents
+ * \param cursor Index of cursor position
+ *
+ * This function returns the index of the word from an array made by splitting
+ * \p line on consecutive occurrences of \c IFS.
+ *
+ * \return Index of word
+ */
int rl_word(const char * line, int cursor);
-char ** rl_complete_list(const char * word, const char * suggestions[]);
+/**
+ * \brief Create a completion suggestion string array for readline
+ *
+ * \param word Word to complete
+ * \param options List of possible choices (NULL terminated array of strings)
+ *
+ * \return Suggestions matching \p word
+ */
+char ** rl_complete_list(const char * word, const char * options[]);
+
+/// \}
diff --git a/client/sock.cpp b/client/sock.cpp
index 3490586..e33a3dc 100644
--- a/client/sock.cpp
+++ b/client/sock.cpp
@@ -101,7 +101,7 @@ void PBSocket::sock_task() {
if (ret > 0) continue;
// message read completely!
- i2c_recv(input.addr, input.data, input.length);
+ i2c_recv(input.data, input.length);
free(input.data);
}
diff --git a/client/sock.h b/client/sock.h
index 0dee09e..792123e 100644
--- a/client/sock.h
+++ b/client/sock.h
@@ -3,29 +3,72 @@
#include <cstdint>
#include <thread>
+/**
+ * \ingroup pbc
+ * \defgroup pbc_sock Socket
+ * \brief TCP socket handling
+ * \{
+ */
+
+/**
+ * \brief Asynchronous puzzle box socket connection
+ * \note Once connected, this class will call \c i2c_recv() when a complete I2C
+ * message has been received
+ */
class PBSocket {
public:
PBSocket();
PBSocket(const char * addr, uint16_t port);
virtual ~PBSocket();
+ //! Configure target server
void set_server(const char * addr, uint16_t port);
+ //! Attempt to connect to server and start \c sock_task() in a thread
void sock_connect();
+ /**
+ * \brief Send data over the TCP connection
+ *
+ * \param buf Data to send
+ * \param buf_sz Size of \p buf in bytes
+ */
void send(const char * buf, size_t buf_sz);
private:
+ /**
+ * \brief Continously read from the TCP socket and read \ref i2ctcp messages
+ * using \c i2ctcp_read().
+ *
+ * Once a complete message has been parsed, \c i2c_recv() is called with the
+ * complete message. This message is automatically free'd after \c i2c_recv()
+ * returns.
+ *
+ * \note This function is run in a separate thread
+ */
void sock_task();
+ //! Close the socket
void sock_close();
+ //! Pointer to thread running \c sock_task()
std::thread* _thread = nullptr;
+ /**
+ * \brief IP address of server to connect to
+ *
+ * \note This member must contain an IP address, as no hostname resolution is
+ * done in pbc.
+ */
const char * _addr = NULL;
+ //! Port number of server to connect to
uint16_t _port = 0;
+ //! Unix file descriptor of opened socket
int _fd = -1;
};
+//! Singleton \c PBSocket instance
extern PBSocket* sock;
+/// \}
+
diff --git a/client/xxd.h b/client/xxd.h
index fb28bb1..ede9fff 100644
--- a/client/xxd.h
+++ b/client/xxd.h
@@ -7,10 +7,19 @@ extern "C" {
#endif
/**
+ * \ingroup pbc
+ * \defgroup pbc_xxd xxd
+ * \brief Utility hexdump
+ * \{
+ */
+
+/**
* \brief utility function that prints hexdump of data
*/
void xxd(const char * data, size_t size);
+/// \}
+
#ifdef __cplusplus
}
#endif
diff --git a/docs/.gitignore b/docs/.gitignore
index a2f45c2..da49ef2 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -1,5 +1,6 @@
*.pdf
res
+.$*.bkp
# i know this is bad
Gemfile.lock
diff --git a/docs/design.adoc b/docs/design.adoc
index 5ebbb15..6df83b6 100644
--- a/docs/design.adoc
+++ b/docs/design.adoc
@@ -13,7 +13,7 @@ structure, and has three levels of design 'depth':
Only design details deemed relevant by the document authors are documented
here. Low-level implementation details such as API interfaces, code paths and
-workarounds are documented inside the source code repository.
+workarounds are documented with Doxygen cite:[pbdox].
[[sec:lv1]]
== Top-Level
@@ -34,8 +34,9 @@ main controller and multiple puzzle modules. Other notable details include:
time of writing (2024-03-11), and this project only describes the interface
between the puzzle box and the bomb.
* The puzzle box is capable of bidirectional communication over Wi-Fi. This
- connection is used to configure the puzzle box before gameplay or modify its
- state during gameplay.
+ connection is used to configure the puzzle box before gameplay or modify its
+ state during gameplay (<<reqs.adoc#req:edge-manual-reset>>,
+ <<reqs.adoc#req:edge-skip-puzzle>>).
[[fig:system-top]]
.Context block diagram
@@ -92,8 +93,11 @@ The criteria for a puzzle module controller are:
The research document cite:[research] compares various microcontrollers
matching these criteria. As a result of this research, the Microchip
PIC16F15276 was selected as the recommended microcontroller for future puzzle
-modules. The current development hardware utilizes an ESP32-PICO-D4 module, so
-the puzzle module software is written with portability in mind.
+modules.
+
+NOTE: The current development hardware still utilizes an ESP32-PICO-D4 module,
+but due to a misunderstanding cite:[handover], Arduino boards were used to
+implement the puzzle modules.
[[fig:puzzle-module-top]]
.Generic puzzle module top-level block diagram
@@ -117,7 +121,7 @@ the following:
** Aggregating game state for all installed puzzle modules.
** Reading and writing game state for all installed puzzle modules.
** Broadcasting updates internally.
-* Serve TCP socket connections for—
+* Serve a TCP socket for—
** Sending state updates
** Manually updating game state
** Integration with the bomb
@@ -147,6 +151,12 @@ The requirements document compares various microcontrollers that fit these
criteria. After this comparison, the decision was made to utilize the Raspberry
Pi Pico W as main controller during development.
+NOTE: This was written while we did not know the puzzle bus specifically
+requires slave-addressible I^2^C multi-master controllers to function properly.
+The RP2040 was still used, but has required implementing workarounds. Please
+see the handover report for more details on how this impacted the project
+cite:[handover].
+
[[fig:main-controller-top]]
.Main controller top-level block diagram
image::img/main-controller-top.svg[]
@@ -165,12 +175,28 @@ peripherals is handled through a central I^2^C bus referred to as the 'puzzle
bus'. This design was again carried over from the hardware design from the
21-22 group cite:[2122_design].
-The only notable difference made this year was the removal of the
-"HarwareInterrupt" line1{empty}footnote:[This is not a typo], which was
-connected but not utilized cite:[research].
-
-Address definitions and protocol specifications are further detailed in
-<<sec:lv2-bus>>.
+The previously specified "HarwareInterrupt" line1{empty}footnote:[This is not a
+typo] has been removed this year, as it was connected but not utilized
+cite:[research].
+
+To optimize for flexibility and extensibility, the puzzle bus should ideally
+function as a network (similar to the CAN bus), to allow puzzle modules to send
+responses asynchronously. I^2^C was initially chosen for the puzzle bus due to
+its widespread availability on microcontrollers and in peripherals, but does
+not provide any network-like capabilities.
+
+To archive network-like capabilities, the puzzle bus is specified to be a
+multi-master I^2^C bus, and all puzzle modules are specified to be I^2^C
+multi-master controllers that are slave-addressible. The multi-master part is
+required to prevent I^2^C transmissions from being corrupted in the event of a
+bus collision, and the slave-addressible part is required to both send and
+receive messages on the same controller. This can also be achieved by using 2
+I^2^C peripherals on the same bus simultaniously, which is what the RP2040
+currently uses. This has required changes to the wiring, and is the only
+hardware-level specification made this year.
+
+More details on the messages sent over the puzzle bus are described in
+<<sec:lv3-pb-messages>>.
=== Power supply
@@ -202,15 +228,39 @@ image::img/system-bus.svg[]
[[sec:lv2]]
== Modules
-This section elaborates on the top-level specifications from <<sec:lv1>> with
-additional hardware specifications and software design decisions.
+This section elaborates on the top-level (hardware) specifications from
+<<sec:lv1>> with software design decisions.
+
+=== Software module separation
+
+[[fig:software-component]]
+.Software library components
+image::img/software-components.svg[]
+
+<<fig:software-component>> shows a software component diagram with an example
+Arduino-based puzzle module, the main controller and the puzzle box client.
+Notable properties of this architecture include:
-=== Puzzle Module Framework
+* The Arduino SDK, FreeRTOS, mpack, and RPI Pico SDK are external libraries,
+ and with the exception of mpack, these have not been modified.
+* The puzzle bus driver is split into a (portable) standalone library and a
+ module-specific driver.
+* There is a separate library for (de)serializing I^2^C commands for
+ transmission over TCP.
-This subsection defines aspects of the 'puzzle framework' and the interface
-that allows puzzle modules to integrate with this framework. All communication
-described within this subsection refers to 'internal' communication between the
-main controller and puzzle module.
+The specific decision to split the puzzle bus driver and create a separate
+I^2^C over TCP library was made to avoid writing a command set separate from
+internal puzzle bus commands (i.e. one specific to TCP connections). This
+architecture allows the puzzle box client to not only control the main
+controller, but also directly inspect puzzle bus messages for debugging and
+development of future puzzle modules (<<reqs.adoc#req:main-static>>).
+
+=== Puzzle module framework
+
+This subsection defines aspects of the 'puzzle framework': the interface that
+allows puzzle modules to integrate with the puzzle bus and main controller. All
+communication described within this subsection refers to 'internal'
+communication between the main controller and puzzle modules on the puzzle bus.
The puzzle framework is the foundation of the puzzle box software, and is
designed to facilitate the following:
@@ -222,107 +272,198 @@ designed to facilitate the following:
* Provide abstracted interfaces to allow for easy integration of the puzzle box
as part of a larger whole (<<reqs.adoc#req:main-interface>>).
+==== Guidelines
+
+The following assumptions are made about puzzle modules:
+
+* Puzzle modules do not take initiative to send REQ or SET commands. They only
+ respond to requests from the main controller.
+* Puzzle modules are I^2^C multi-master controllers that are slave-addressable
+ in master mode.
+* The main controller is a puzzle module, but with the following differences:
+** The main controller is allowed to initiate REQ and SET commands.
+** The main controller's global state is an aggregation of all other puzzle
+ modules, and ignores STATE SET commands.
+
+These guidelines allow the following simplifications:
+
+* Puzzle modules may assume they are always being addressed by the main
+ controller (this simplifies the message architecture).
+* The puzzle bus may be shared with regular I^2^C peripherals without causing
+ issues.
+
+[[sec:lv3-pb-messages]]
+==== Messages
+
+Puzzle bus messages consist of a simple header and variable data. This format
+is shown in <<tab:pb-msg-fmt>>. The messages are (de)serialized using mpack.
+This choice was made after considering various alternative options for sending
+structured messages cite:[research]. Note that all messages are sent as I^2^C
+writes. Due to this, the I^2^C address of a message sender is included in the
+header to facilitate network-like features over I^2^C.
+
+[[tab:pb-msg-fmt]]
+.Puzzle bus message format
+[%autowidth]
+|===
+| Field | Content
+
+| type | Command type (see <<tab:pb-msg-types>>)
+| action | Command action (see <<tab:pb-msg-actions>>)
+| sender | I^2^C address of sender
+| cmd | Command data (dependent on ``type``)
+|===
+
+<<tab:pb-msg-types>> lists the different command types.
+
+[[tab:pb-msg-types]]
+.Puzzle bus command types
+[cols="10,~"]
+|===
+| Type | Description
+
+| ``MAGIC``
+| The MAGIC command effectively serves as a 'secret handshake' (using a _magic_
+value) which is used to distinguish between puzzle modules and unrelated I^2^C
+devices.
+
+| ``STATE``
+| The STATE command is used by puzzle modules to inform the main controller about
+their global state (see <<sec:framework-state>>). The main controller
+aggregates the states of all connected puzzle modules and exchanges this
+aggregated state with the puzzle modules to indicate when the entire puzzle box
+is solved.
+
+| ``PROP``
+| The PROP command type is used for exchanging arbitrary data between puzzle
+modules and/or the puzzle box client (pbc) over the <<sec:main-bridge,TCP
+bridge>>. These properties are not used by the puzzle framework, and serve as
+an extensible interface for puzzle module developers to use.
+|===
+
+<<tab:pb-msg-actions>> lists the different command actions.
+
+[[tab:pb-msg-actions]]
+.Puzzle bus command actions
+[cols="10,~"]
+|===
+| ``REQ``
+| Mark the command as a request. The receiver of this message is expected to
+return a message of the same type, but with a RES action.
+
+| ``RES``
+| Mark the command as a response to a REQ message. All REQ messages should be
+followed by a RES message.
+
+| ``SET``
+| Request a change / write. The SET command is never followed by a RES.
+|===
+
+Please note that not all commands define behavior for all actions (e.g. there
+is no MAGIC SET command).
+
+Only the MAGIC and STATE commands are required for the puzzle box to function.
+The PROP command was created to allow future expansion without modifying the
+main controller firmware (<<reqs.adoc#req:main-static>>).
+
+The specific format of the 'cmd' field from <<tab:pb-msg-fmt>> is different for
+each command type, and is for this reason only documented in-code using
+Doxygen cite:[pbdox].
+
[[sec:framework-state]]
==== State
All puzzle modules implement the same state machine shown in
-<<fig:puzzle-module-common-state>>. Note that the arrows indicate state
-transitions that a puzzle module may take on its own. The main controller also
-allows the game operator to manually set the current state as one of the states
-on the right half of <<fig:puzzle-module-common-state>>, which can be used to
-skip a puzzle if a player is stuck (<<reqs.adoc#req:edge-skip-puzzle>>) or
-reset a game if it is malfunctioning (<<reqs.adoc#req:edge-manual-reset>>).
-
-Puzzle modules start in the 'uninitialized' state, where they repeatedly send
-messages to the main controller (see <<sec:main-bridge>>). The state transition
-from 'uninitialized' to 'reset' is forced by the main controller upon
-initialization. States on the right half of <<fig:puzzle-module-common-state>>
-are used during gameplay.
+<<fig:puzzle-module-common-state>>. Note that continuous arrows indicate state
+transitions that a puzzle module may take on its own, while dashed arrows
+indicate state transitions forced by the main controller. The main controller
+also allows the game operator to manually set a module's global state to one of
+these states, which can be used to skip a puzzle if a player is stuck
+(<<reqs.adoc#req:edge-skip-puzzle>>) or reset a game if it is malfunctioning
+(<<reqs.adoc#req:edge-manual-reset>>).
[[fig:puzzle-module-common-state]]
.Global puzzle module state machine
image::img/puzzle-module-common-state.svg[]
-The state machine described in <<fig:puzzle-module-common-state>> is referred
-to as the global state. Puzzle modules may also declare and define custom state
-variables, which is referred to as auxiliary state. These auxiliary state
-variables contain game-specific variables; e.g. the binary state of each button
-on the Neotrellis puzzle module, or the last passcode entered on the vault
-puzzle module.
-
-Separating the auxiliary state from the generic state allows the main
-controller to handle the auxiliary state as an arbitrary blob, which allows for
-future expansion without modification of the main controller software.
+Puzzle modules start in the 'uninitialized' state, where they wait until the
+main controller sends a REQ STATE command. Receiving this command indicates to
+the puzzle module that it was successfully registered by the main controller,
+and that it may transition from the 'uninitialized' state to the 'idle' state.
+This process is also shown in <<fig:sequence-puzzle-module-init>>.
-==== Commands
+The state machine described in <<fig:puzzle-module-common-state>> is referred
+to as the global state. Puzzle modules may also declare and define custom
+variables, which are referred to as properties. These properties may contain
+game-specific variables; e.g. the binary state of each button on the Neotrellis
+puzzle module, or the last passcode entered on the vault puzzle module.
+
+Separating properties from the global state allows the main controller to
+handle these property values as an arbitrary blob, which allows for future
+expansion without modification of the main controller software
+(<<reqs.adoc#req:main-static>>).
+
+==== I^2^C addresses
+
+The RPI Pico SDK prohibits the use of I^2^C addresses reserved by the I^2^C
+specification. This means different addresses from previous years are used.
+These addresses are indexed in the code in a header exposed by the puzzle bus
+driver cite:[pbdox].
+
+The I^2^C addresses are also used to determine the puzzle sequence (i.e. the
+order in which puzzle modules are set to the 'playing' state). The sequence is
+determined by the main controller on startup, and consists of the connected
+puzzle modules' addresses in descending order (i.e. highest address first).
+Note that the same I^2^C address may be used by two different puzzle modules,
+but this will make it impossible for them to be used simultaniously.
-The puzzle module framework describes the following commands:
+=== Main Controller
-* Read state
-* Write state
-* Update
+This subsection defines the function and state of the main controller.
-The 'read' and 'write' commands are used to communicate both types of state
-defined in <<sec:framework-state>>.
+==== Initializing puzzle modules
-To avoid issues caused by state synchronization memory consumption on the main
-controller and puzzle modules, auxiliary state is only stored on each
-respective puzzle module's controller. Only global state is cached on the main
-controller to reduce the number of back-and-forth messages required for state
-updates.
+The main controller sends a MAGIC REQ command to every I^2^C address on
+startup. Puzzle modules start in the 'uninitialized' state (see
+<<fig:puzzle-module-common-state>>), during which they do nothing. Puzzle
+modules in this state are still able to reply to requests, including MAGIC REQ
+commands. When the main controller receives a MAGIC RES command, the I^2^C
+address of the sender is added to an internal list of I^2^C devices that are
+considered puzzle modules.
-These commands are sufficient to realize the puzzle box, but this means that
-the puzzle box would rely heavily on polling-based updates internally. To solve
-this, the 'update' command was created. This command is utilized for various
-kinds of updates, including registering new puzzle modules and updating global
-state.
+After the initial handshake request 'wave' (bus scan), all puzzle modules are
+repeatedly asked for their global state using a STATE REQ command. This request
+also includes the global state of the requesting puzzle module, which is always
+the main controller (under normal circumstances). Upon receiving the first
+STATE REQ command, a puzzle module knows it has been registered successfully by
+the main controller, and transitions into the 'idle' state.
-=== Main Controller
+[[fig:sequence-puzzle-module-init]]
+.Puzzle module initialization sequence diagram
+image::img/sequence-puzzle-module-init.svg[]
-This subsection defines the function and state of the main controller.
+(Activated lifeline indicates the module is no longer in 'uninitialized' state)
==== State
-The global state of the main controller is an aggregated version of all
-installed puzzle modules and is defined by the state machine shown in
+The global state of the main controller is an aggregation of all installed
+puzzle modules and is defined by the state machine shown in
<<fig:main-controller-state>>.
[[fig:main-controller-state]]
.Main controller global state machine
image::img/main-controller-state.svg[]
-The following list describes when each state is active:
+The main controller global state is determined using the following rules:
-* If all puzzle modules are in the 'reset' state, the main controller is also
- in the 'reset' state.
+* If all puzzle modules are in the 'idle' state, the main controller is also in
+ the 'idle' state.
* If all puzzle modules are in the 'solved' state, the main controller is also
- in the 'solved' state.
+ in the 'solved' state.
* Else, the main controller is in the 'playing' state.
-Because the main controller's state is only dependent on the installed puzzle
-modules' state, it is only updated when a puzzle module sends an update
-notification. When the global state of the main module changes, an update
-broadcast is sent to all puzzle modules.
-
-To simplify the commands used to control the puzzle box, the list of installed
-puzzle modules is stored as an auxiliary state variable of the main controller.
-
-==== Initializing Puzzle Modules
-
-Puzzle modules start in the 'uninitialized' state (see
-<<fig:puzzle-module-common-state>>). In this state, the puzzle module
-repeatedly sends an update command to the main controller. The main controller
-responds to this message by sending a 'set state' command with the target state
-as 'reset' as reply. Before this response is sent, the main controller
-internally adds the bus address of the puzzle module requesting to be
-initialized to the list of installed puzzle modules. From the main controller's
-point of view, this reply marks the moment the initialization is complete.
-
-[[fig:sequence-puzzle-module-init]]
-.Puzzle module initialization sequence diagram
-image::img/sequence-puzzle-module-init.svg[]
-
-(Activated lifeline indicates the module is no longer in 'uninitialized' state)
+Due to the repeated STATE REQ commands, this effectively informs the puzzle
+modules when the puzzle box is completely solved.
[[sec:main-bridge]]
==== Bridge
@@ -333,99 +474,30 @@ The Raspberry Pi 3B+ used as main controller during the 21-22 run of the
project set up a Wi-Fi Mesh network cite:[2122_design] to communicate with the
puzzle box. This year's main controller (Raspberry Pi Pico W cite:[research])
uses a standard 802.11b/g/n access point instead
-(<<reqs.adoc#req:main-802-11-ap>>).
-
-On this network, the main controller hosts a server that serves TCP socket
-connections. These sockets directly forward all internal messages sent to the
-main controller bidirectionally (i.e. on behalf of the main controller).
-Detailed specifications on the TCP socket server are in
-<<sec:lv3-remote-control>>.
+(<<reqs.adoc#req:main-802-11-ap>>) as it is a simpler solution.
-==== Operating System
+On this network, the main controller hosts a server that serves a TCP socket
+connection. This socket is used to directly forward all internal messages sent
+on the puzzle bus to the puzzle box client bidirectionally (on behalf of the
+main controller).
-The research document cite:[research] contains a detailed comparison of various
-operating systems that are suitable to realize the functionality described in
-this section. After this comparison, the decision was made to utilize FreeRTOS
-as the operating system on the Rasberry Pi Pico W.
+Due to the separation of the puzzle bus driver code into a standalone library
+for reading/writing puzzle bus commands, and a puzzle module-specific code, the
+puzzle box client is able to read/write raw I^2^C commands directly. A separate
+library was made for serializing I^2^C messages so they can be sent over the
+TCP connection. This library is documented in detail using Doxygen cite:[pbdox].
-[[sec:lv2-bus]]
-=== Puzzle Bus
+==== Operating system
-This section describes the addresses and communication protocol used on the
-puzzle bus. These specifications only apply to messages sent internally in the
-puzzle box, as messages forwarded by the bridge (see <<sec:main-bridge>>) are
-sent on behalf of the main controller.
+Because the main controller needs to asynchronously handle state exchanges with
+puzzle modules while serving a TCP socket connection, the decision to use a
+task scheduler was made. Due to the requirement that most software should be
+covered by the standard curriculum (<<reqs.adoc#req:curriculum-cov>>), this
+choice was between FreeRTOS and Zephyr. FreeRTOS was chosen because it is the
+simplest solution, and because the features Zephyr offers over FreeRTOS are
+already present in the Raspberry Pi Pico SDK.
-==== Addresses
-
-The I^2^C addresses remain mostly unchanged from the 20-21 group's
-implementation cite:[2021_design]. Addresses that were modified since the 20-21
-implementation are marked with an asterisk. Table 1 lists these addresses for
-reference. These addresses are also used to identify specific puzzle modules.
-
-.I^2^C address reference
-[%autowidth]
-|===
-| Peripheral | Address
-
-| Main controller | 0x10*
-| Neotrellis puzzle controller | 0x11*
-| Neotrellis button matrix | 0x12*
-| Software puzzle controller | 0x03
-| Hardware puzzle controller | 0x04
-| Vault puzzle controller | 0x06
-|===
-
-==== Messages
-
-All messages sent over the puzzle bus have a similar format. This format is
-shown in Table 2. Notable details include:
-
-The 'subject' field does not have to match the I^2^C address of the message
-sender or recipient
-
-Property 0x00 stores a module's global state
-
-.Puzzle bus message format
-[%autowidth]
-|===
-| Field | Content
-
-| Command | Enum: read, write, update
-| Subject | I^2^C address (7-bit)
-| Property | Address (8-bit)
-| Value | Byte string (variable length)
-|===
-
-The messages described in Table 2 are (de)serialized using Google's protocol
-buffer library. This choice was made after considering various alternative
-options for sending structured messages cite:[research].
-
-<<fig:sequence-puzzle-module-init>> shows an example of how messages are
-exchanged for the initialization of a puzzle module.
-
-<<fig:sequence-puzzle-finish>> shows an example exchange where the last puzzle
-module (A) is solved while (B) is already solved.
-
-. First, module A sets it's own state to 'solved' and subsequently informs the
- main controller of this change.
-. As a result of this update notification, the main controller queries puzzle
- module A for its new global state.
-. Once the main controller has received and confirmed that all puzzle module
- global states are set to 'solved', the main controller sets its own state to
- 'solved', and broadcasts an update message to all puzzle modules.
-. As a result of the update message from the main controller, module B requests
- the main controller's new global state, and is able to verify that all puzzle
- modules have been solved.
-
-In this example, module B could be the vault puzzle module, which displays a
-code when the entire puzzle box is solved.
-
-[[fig:sequence-puzzle-finish]]
-.Puzzle box finish sequence diagram
-image::img/sequence-puzzle-finish.svg[]
-
-=== NeoTrellis Puzzle
+=== NeoTrellis puzzle
This subsection defines aspects of the 'NeoTrellis puzzle' module and gives a
summary of how the puzzle is meant to be solved. This module will be created to
@@ -439,8 +511,8 @@ button. The way to solve this puzzle is by dimming every Neopixel in the 8x8
matrix. This is done by clicking on a button, which switches the state of the
Neopixel underneath the pixel and the Neopixels in each cardinal direction from
the pressed button. This means that if a Neopixel was on and the button was
-pressed it will turn off and vice-versa. A visual example can be found in
-Appendix B.
+pressed it will turn off and vice-versa.
+// A visual example can be found in Appendix B.
==== Puzzle inputs & outputs
@@ -452,7 +524,7 @@ diagram has been shown in <<fig:neotrellis-io>>.
.NeoTrellis puzzle in-out
image::img/neotrellis-io.png[]
-=== Software Puzzle
+=== Software puzzle
This subsection defines aspects of the 'software puzzle' module and gives a
summary of how the puzzle is meant to be solved. This module will be created to
@@ -468,7 +540,8 @@ have their own logical circuit engraved in the box, and the 6 input ports on
the right side of the puzzle have a letter (A through F) engraved in the box.
The way to solve the puzzle is by connecting the banana plug cable from an
input port on the left side of the puzzle to the corresponding input port on
-the right side of the puzzle. An example of this can be found in Appendix C.
+the right side of the puzzle.
+// An example of this can be found in Appendix C.
When the puzzle starts, the participants of the game will have 6 code-fragments
written on paper, corresponding to the logical circuits on the puzzle box. The
@@ -492,9 +565,9 @@ code. This is shown in <<fig:software-io>>.
.Software puzzle in-out
image::img/software-io.png[]
-=== Hardware Puzzle
+=== Hardware puzzle
-==== Hardware Puzzle gameplay
+==== Hardware puzzle gameplay
The hardware puzzle has a logic gate puzzle engraved on the front plate of the
puzzle box. To solve the puzzle, the user must set the toggle switches to the
@@ -512,7 +585,7 @@ The inputs and outputs of this puzzle have been taken from the design document
of the previous group which worked on this project (21-22). This input and
output diagram has been shown in Figure ??.
-=== Vault Puzzle
+=== Vault puzzle
==== Vault puzzle gameplay
@@ -529,40 +602,4 @@ clicked the vault resets and they need to start over from the beginning.
.Vault puzzle in-out
image::img/vault-io.png[]
-=== Bomb device
-
-==== Bomb device connection
-
-The bomb connects to a WiFi-network using the 802.11x standard. The hub hosts
-an interface that can be used to identify all the devices including the bomb
-and also pair it to a puzzlebox. After that the game can be set-up and a given
-countdown time and start time will be communicated to the bomb over a TCP
-socket connection. The hub generates a code that will be send to both the
-puzzlebox and bomb so that both devices know what would be or can be expected.
-
-The bomb can also use the WiFi connection to sync. the time.
-
-==== Device inputs & outputs
-
-[[fig:bomb-io]]
-.Bomb device in-out
-image::img/bomb-io.png[]
-
-== Components
-[[sec:lv3-remote-control]]
-=== Remote Control
-==== Socket Server
-==== Socket Commands
-=== Neotrellis Puzzle
-=== Game state diagrams, activity diagrams (if applicable)
-=== Software Puzzle
-=== Hardware Puzzle
-=== Vault Puzzle
-
-[appendix]
-== NeoTrellis puzzle example
-
-[appendix]
-== Software puzzle example
-
include::share/footer.adoc[]
diff --git a/docs/doxygen-layout.xml b/docs/doxygen-layout.xml
new file mode 100644
index 0000000..9ac2aaa
--- /dev/null
+++ b/docs/doxygen-layout.xml
@@ -0,0 +1,62 @@
+<!--
+ This file is largely based off /templates/general/layout_default.xml from
+ <https://github.com/doxygen/doxygen>. The official documentation for this
+ XML file is at <https://www.doxygen.nl/manual/customize.html>.
+-->
+<doxygenlayout version="1.0">
+ <navindex>
+ <tab type="mainpage" visible="yes" title="Index"/>
+ <tab type="topics" visible="yes" title="Components"/>
+ </navindex>
+ <group>
+ <briefdescription visible="yes"/>
+ <detaileddescription visible="yes"/>
+ <groupgraph visible="yes"/>
+ <memberdecl>
+ <nestedgroups visible="yes" title="Components"/>
+ <modules visible="yes"/>
+ <dirs visible="yes"/>
+ <files visible="yes"/>
+ <namespaces visible="yes"/>
+ <concepts visible="yes"/>
+ <classes visible="yes"/>
+ <defines/>
+ <typedefs/>
+ <sequences/>
+ <dictionaries/>
+ <enums/>
+ <enumvalues/>
+ <functions/>
+ <variables/>
+ <signals/>
+ <publicslots/>
+ <protectedslots/>
+ <privateslots/>
+ <events/>
+ <properties/>
+ <friends/>
+ <membergroups visible="yes"/>
+ </memberdecl>
+ <memberdef>
+ <pagedocs/>
+ <inlineclasses/>
+ <defines/>
+ <typedefs/>
+ <sequences/>
+ <dictionaries/>
+ <enums/>
+ <enumvalues/>
+ <functions/>
+ <variables/>
+ <signals/>
+ <publicslots/>
+ <protectedslots/>
+ <privateslots/>
+ <events/>
+ <properties/>
+ <friends/>
+ </memberdef>
+ <authorsection visible="yes"/>
+ </group>
+</doxygenlayout>
+
diff --git a/docs/fat.adoc b/docs/fat.adoc
new file mode 100644
index 0000000..29622e2
--- /dev/null
+++ b/docs/fat.adoc
@@ -0,0 +1,289 @@
+:document: Factory Acceptance Test
+include::share/meta.adoc[]
+
+== Introduction
+// TODO: Make an intro
+
+=== Compatibility matrix
+[cols="1,9*^", options="header"]
+|===
+| Requirement \\ Test | T-01 | T-02 | T-03 | T-04 | T-05 | T-06 | T-07 | T-08 | T-09
+
+| xref:reqs.adoc#R-001[R-001] | xref:#Test-01[✓] | | | | | | | |
+| xref:reqs.adoc#R-002[R-002] | xref:#Test-01[✓] | | | | | | | |
+| xref:reqs.adoc#R-003[R-003] | xref:#Test-01[✓] | | | | | | | |
+| xref:reqs.adoc#R-004[R-004] | xref:#Test-01[✓] | | | | | | | |
+| xref:reqs.adoc#R-005[R-005] | xref:#Test-01[✓] | | | | | | | |
+| xref:reqs.adoc#R-034[R-034] | xref:#Test-01[✓] | | | | | | | |
+| xref:reqs.adoc#R-036[R-036] | | xref:#Test-02[✓] | | | | | | |
+| xref:reqs.adoc#R-037[R-037] | | xref:#Test-02[✓] | | | | | | |
+| xref:reqs.adoc#R-038[R-038] | | xref:#Test-02[✓] | | | | | | |
+| xref:reqs.adoc#R-166[R-166] | | xref:#Test-02[✓] | | | | | | |
+| xref:reqs.adoc#R-169[R-169] | | xref:#Test-02[✓] | | | | | | |
+| xref:reqs.adoc#R-075[R-075] | | | xref:#Test-03[✓] | | | | | |
+| xref:reqs.adoc#R-076[R-076] | | | xref:#Test-03[✓] | | | | | |
+| xref:reqs.adoc#R-081[R-081] | | | xref:#Test-03[✓] | | | | | |
+| xref:reqs.adoc#R-085[R-085] | | | | xref:#Test-04[✓] | | | | |
+| xref:reqs.adoc#R-087[R-087] | | | | xref:#Test-04[✓] | | | | |
+| xref:reqs.adoc#R-150[R-150] | | | | | xref:#Test-05[✓] | | | |
+| xref:reqs.adoc#R-082[R-082] | | | | | xref:#Test-05[✓] | | | |
+| xref:reqs.adoc#R-083[R-083] | | | | | xref:#Test-05[✓] | | | |
+| xref:reqs.adoc#R-084[R-084] | | | | | xref:#Test-05[✓] | | | |
+| xref:reqs.adoc#R-167[R-167] | | | | | | xref:#Test-06[✓] | | |
+| xref:reqs.adoc#R-168[R-168] | | | | | | xref:#Test-06[✓] | | |
+| xref:reqs.adoc#R-027[R-027] | | | | | | | xref:#Test-07[✓] | |
+| xref:reqs.adoc#R-048[R-048] | | | | | | | | xref:#Test-08[✓] |
+| xref:reqs.adoc#R-049[R-049] | | | | | | | | xref:#Test-08[✓] |
+| xref:reqs.adoc#R-050[R-050] | | | | | | | | xref:#Test-08[✓] |
+| xref:reqs.adoc#R-051[R-051] | | | | | | | | xref:#Test-08[✓] |
+| xref:reqs.adoc#R-052[R-052] | | | | | | | | xref:#Test-08[✓] |
+| xref:reqs.adoc#R-053[R-053] | | | | | | | | xref:#Test-08[✓] |
+| xref:reqs.adoc#R-089[R-089] | | | | | | | | | xref:#Test-09[✓]
+| xref:reqs.adoc#R-090[R-090] | | | | | | | | | xref:#Test-09[✓]
+| xref:reqs.adoc#R-091[R-091] | | | | | | | | | xref:#Test-09[✓]
+| xref:reqs.adoc#R-127[R-127] | | | | | | | | | xref:#Test-09[✓]
+| xref:reqs.adoc#R-128[R-128] | | | | | | | | | xref:#Test-09[✓]
+| xref:reqs.adoc#R-129[R-129] | | | | | | | | | xref:#Test-09[✓]
+| xref:reqs.adoc#R-134[R-134] | | | | | | | | | xref:#Test-09[✓]
+| xref:reqs.adoc#R-135[R-135] | | | | | | | | | xref:#Test-09[✓]
+| xref:reqs.adoc#R-165[R-165] | | | | | | | | | xref:#Test-09[✓]
+|===
+
+=== Neotrellis-puzzle
+
+[#Test-01]
+==== Test 01
+
+===== Covered requirements
+* Technical requirements
+** xref:reqs.adoc#R-034[R-034] (neotrellis function & Arduino init.)
+* Functional requirements
+** *None*
+
+===== Additional setup
+*None*
+
+===== Test
+. Turn both the Arduino and the neotrellis modules on
+
+===== Result
+* [ ] Verify that the neotrellis modules emit light in different colors (init. state).
+
+[#Test-02]
+==== Test 02
+
+===== Covered requirements
+* Technical requirements
+** xref:reqs.adoc#R-166[R-166] (Arduino & RPI Pico I²C communication)
+** xref:reqs.adoc#R-169[R-169] (Arduino & neotrellis I²C communication)
+* Functional requirements
+** xref:reqs.adoc#R-036[R-036] (game logic)
+** xref:reqs.adoc#R-037[R-037] (neotrellis led color)
+** xref:reqs.adoc#R-038[R-038] (game d.o.d.)
+
+===== Additional setup
+* [ ] Connect the Arduino to the maincontroller (RPI Pico) using the I²C interface, pull-up resistors and a common ground.
+
+===== Test
+. Turn both the Arduino and the neotrellis modules on.
+. Wait for a few seconds.
+. Turn the RPI Pico on.
+. Wait for another few seconds.
+. Play the game until you have succeeded.
+
+===== Result
+* [ ] Verify that the puzzle module tries to communicate with the maincontroller.
+* [ ] Verify that a light should be blinking on one of the neotrellis modules.
+* [ ] Press one of the emitting buttons and check if the buttons surrounding it will light
+* [ ] Play the game until no buttons emit light anymore and check if the main controllers wants to load the next puzzle.
+
+=== Vault-puzzle
+
+[#Test-03]
+==== Test 03
+
+===== Covered requirements
+* Technical requirements
+** xref:reqs.adoc#R-151[R-151] (4x 7-seg. type & connection)
+* Functional requirements
+** xref:reqs.adoc#R-075[R-075] (4x 7-seg. availability)
+** xref:reqs.adoc#R-076[R-076] (ventilation)
+** xref:reqs.adoc#R-081[R-081] (4x 7-seg. operation)
+
+===== Additional setup
+* [ ] Connect the Arduino to the maincontroller (RPI Pico) using the I²C interface, pull-up resistors and a common ground.
+
+===== Test
+. Turn the Arduino on.
+. Wait for a few seconds.
+. Turn the RPI Pico on.
+. Wait until the Arduino is in its init. state.
+
+===== Result
+* [ ] Verify that there is a 4x 7-seg. display and working.
+* [ ] Verify that the puzzle module tries to communicate with the maincontroller
+* [ ] Check if after the unit. state (blinking zero's) there is a letter and number displayed on the 4x 7 seg. display.
+
+[#Test-04]
+==== Test 04
+
+===== Covered requirements
+* Technical requirements
+** *None*
+* Functional requirements
+** xref:reqs.adoc#R-085[R-085] (4x 7-seg. operation by passing the game)
+** xref:reqs.adoc#R-087[R-087] (4x 7-seg. operation by failing the game)
+
+===== Additional setup
+*None*
+
+===== Test
+. Turn the Arduino on.
+. Wait for a few seconds.
+. Turn the RPI Pico on.
+. Play the game correctly for 2 levels.
+. Play one level incorrectly.
+
+===== Result
+* [ ] Verify a new code is generated each time you level-up
+* [ ] Verify that an older code is presented each time you level-down
+
+[#Test-05]
+==== Test 05
+
+===== Covered requirements
+* Technical requirements
+** xref:reqs.adoc#R-150[R-150] (button matrix)
+* Functional requirements
+** xref:reqs.adoc#R-082[R-082] (game logic: leveling)
+** xref:reqs.adoc#R-083[R-083] (game logic: level)
+** xref:reqs.adoc#R-084[R-084] (game logic: succeeding level)
+
+===== Additional setup
+* Connect the vault solenoid valve to the Arduino using a MOSFET or other type of driver.
+
+===== Test
+. Turn the Arduino on.
+. Wait for a few seconds.
+. Turn the RPI Pico on.
+. Play the game correctly until you reach the end of the game.
+
+===== Result
+* [ ] Verify that at the last level a code should be displayed that can be used to disarm the "bomb".
+* [ ] Check if the vault itself will unlock and lock again after the game is reset.
+
+=== Puzzle Box Requirements
+
+[#Test-06]
+==== Puzzle Box Basic Setup and Verification
+
+===== Covered requirements
+* Functional requirements
+** xref:reqs.adoc#R-1[R-1] (Puzzle box dimensions)
+** xref:reqs.adoc#R-2[R-2] (Extension on the sides and top)
+** xref:reqs.adoc#R-3[R-3] (Flat bottom)
+** xref:reqs.adoc#R-4[R-4] (Key switch at the bottom of the NeoTrellis puzzle)
+** xref:reqs.adoc#R-5[R-5] (Indicator LED at the bottom of the NeoTrellis puzzle)
+
+===== Additional setup
+* [ ] Measure the dimensions of the puzzle box to ensure compliance with R-1.
+* [ ] Inspect the physical structure for extensions beyond specified limits.
+* [ ] Confirm flatness of the bottom surface.
+* [ ] Locate and identify the key switch and indicator LED as per design specifications.
+
+===== Test
+. Measure and record the dimensions of the puzzle box.
+. Examine the extensions, if any, on the sides and top of the box.
+. Test the flatness of the bottom of the box.
+. Verify the functionality of the key switch.
+. Check the initial state of the indicator LED when power is supplied to the puzzle box.
+
+===== Result
+* [ ] Puzzle box dimensions are within the specified range of 30x30x30 cm ± 5%.
+* [ ] No excess extension beyond 5 cm on any side or the top.
+* [ ] The bottom of the puzzle box is confirmed flat.
+* [ ] The key switch operates as intended.
+* [ ] The indicator LED functions correctly and is visible.
+
+=== Game Functional Requirements Testing
+
+[#Test-07]
+==== Puzzle Module Control Tests
+
+===== Covered requirements
+* Functional requirements
+** xref:reqs.adoc#R-167[R-167] (Manual reset capability of a puzzle module)
+** xref:reqs.adoc#R-168[R-168] (Manual solve capability of a puzzle module)
+
+===== Additional setup
+* [ ] Ensure access to the game operator controls for manual reset and solve.
+
+===== Test
+. Perform a manual reset of a puzzle module during gameplay to verify it resets correctly.
+. Manually set a puzzle module as solved and observe if the system acknowledges the solve appropriately.
+
+===== Result
+* [ ] Puzzle module resets correctly when manually triggered.
+* [ ] Puzzle module is recognized as solved when set manually.
+
+[#Test-08]
+==== Puzzle Difficulty Verification
+
+===== Covered requirements
+* Functional requirements
+** xref:reqs.adoc#R-27[R-27] (Puzzle solvability without prior knowledge)
+
+===== Test
+. Invite testers unfamiliar with the game to solve the puzzles.
+. Record the ease or difficulty encountered by the testers in solving the puzzles.
+
+===== Result
+* [ ] Testers without prior knowledge are able to solve the puzzles, indicating appropriate difficulty levels.
+
+=== Hardware Puzzle Module Testing
+
+[#Test-09]
+==== Initial Setup Verification
+
+===== Covered requirements
+* Functional requirements
+** xref:reqs.adoc#R-58[R-58] (Game operator initial switch position)
+** xref:reqs.adoc#R-59[R-59] (Game operator initial potentiometer position)
+
+===== Additional setup
+* [ ] Access to hardware puzzle board controls for switches and potentiometers.
+
+===== Test
+. Manually set all switches on the hardware puzzle board to the down position.
+. Turn all potentiometers fully to the left to their zero position.
+
+===== Result
+* [ ] All switches are confirmed to be in the down position at the start of the game.
+* [ ] All potentiometers are set to zero at the beginning of the game, indicating correct initial setup.
+
+[#Test-10]
+==== Hardware Component Functionality
+
+===== Covered requirements
+* Functional requirements
+** xref:reqs.adoc#R-48[R-48] (Presence of eight switches)
+** xref:reqs.adoc#R-49[R-49] (Combinatorial circuit functionality)
+** xref:reqs.adoc#R-50[R-50] (7-segment 4-digit display presence and functionality)
+** xref:reqs.adoc#R-51[R-51] (Four potentiometers)
+** xref:reqs.adoc#R-52[R-52] (Blue LED displaying Morse code)
+** xref:reqs.adoc#R-53[R-53] (Green LED indicating solved state)
+
+===== Additional setup
+* [ ] Ensure all hardware components are installed as per the design specifications.
+
+===== Test
+. Verify the presence and functionality of eight switches linked to the combinatorial circuit.
+. Confirm that the combinatorial circuit operates as depicted in the provided diagram.
+. Check the 7-segment display and potentiometers for correct operation.
+. Observe the blue LED for Morse code display and green LED for indicating the puzzle is solved.
+
+===== Result
+* [ ] Eight switches are operational and affect the combinatorial circuit as expected.
+* [ ] The combinatorial circuit correctly processes inputs to produce the expected output.
+* [ ] The 7-segment display and potentiometers function correctly, displaying values as manipulated.
+* [ ] Blue LED successfully displays Morse code, and green LED lights up when the puzzle is solved.
diff --git a/docs/figs.drawio b/docs/figs.drawio
index a40503b..d898390 100644
--- a/docs/figs.drawio
+++ b/docs/figs.drawio
@@ -1,4 +1,4 @@
-<mxfile host="Electron" modified="2024-03-17T13:05:37.082Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/23.1.5 Chrome/120.0.6099.109 Electron/28.1.0 Safari/537.36" etag="7STPuaY27yiGeP_RMlUo" version="23.1.5" type="device" pages="12">
+<mxfile host="Electron" modified="2024-06-20T14:41:34.614Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.5.3 Chrome/124.0.6367.207 Electron/30.0.6 Safari/537.36" etag="OCDtaLfNnSZV2pZT5927" version="24.5.3" type="device" pages="10">
<diagram name="planning-condensed" id="ntlEKQOA_ElMvQzKZB-_">
<mxGraphModel dx="1646" dy="488" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
@@ -213,11 +213,11 @@
</mxGraphModel>
</diagram>
<diagram id="n9IdmxlkFl1pJjqhBrGT" name="system-bus">
- <mxGraphModel dx="1422" dy="822" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+ <mxGraphModel dx="566" dy="347" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
- <mxCell id="EFqebEYhPqh4IJWovyJC-1" value="Puzzle bus&lt;br&gt;(I²C + power)" style="line;strokeWidth=4;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;align=right;labelPosition=left;verticalLabelPosition=middle;verticalAlign=middle;spacingTop=0;spacing=8;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="EFqebEYhPqh4IJWovyJC-1" value="puzzle bus&lt;br&gt;(I²C + power)" style="line;strokeWidth=4;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;align=right;labelPosition=left;verticalLabelPosition=middle;verticalAlign=middle;spacingTop=0;spacing=8;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry x="80" y="110" width="320" height="20" as="geometry" />
</mxCell>
<mxCell id="EFqebEYhPqh4IJWovyJC-3" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=classic;startFill=1;fontFamily=Arial;" parent="1" source="EFqebEYhPqh4IJWovyJC-2" target="EFqebEYhPqh4IJWovyJC-1" edge="1">
@@ -228,7 +228,7 @@
</Array>
</mxGeometry>
</mxCell>
- <mxCell id="EFqebEYhPqh4IJWovyJC-2" value="Main controller" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="EFqebEYhPqh4IJWovyJC-2" value="main controller" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry x="80" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="EFqebEYhPqh4IJWovyJC-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=classic;startFill=1;fontFamily=Arial;" parent="1" source="EFqebEYhPqh4IJWovyJC-4" target="EFqebEYhPqh4IJWovyJC-1" edge="1">
@@ -239,7 +239,7 @@
</Array>
</mxGeometry>
</mxCell>
- <mxCell id="EFqebEYhPqh4IJWovyJC-4" value="Puzzle module 3&lt;br&gt;(neotrellis)" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="EFqebEYhPqh4IJWovyJC-4" value="neotrellis puzzle module" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry x="200" y="160" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="EFqebEYhPqh4IJWovyJC-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=classic;startFill=1;fontFamily=Arial;" parent="1" source="EFqebEYhPqh4IJWovyJC-5" target="EFqebEYhPqh4IJWovyJC-1" edge="1">
@@ -250,7 +250,7 @@
</Array>
</mxGeometry>
</mxCell>
- <mxCell id="EFqebEYhPqh4IJWovyJC-5" value="Puzzle module 4&lt;br style=&quot;border-color: var(--border-color);&quot;&gt;(safe)" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="EFqebEYhPqh4IJWovyJC-5" value="vault puzzle module" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry x="320" y="160" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="EFqebEYhPqh4IJWovyJC-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=classic;startFill=1;fontFamily=Arial;" parent="1" source="EFqebEYhPqh4IJWovyJC-6" target="EFqebEYhPqh4IJWovyJC-1" edge="1">
@@ -261,7 +261,7 @@
</Array>
</mxGeometry>
</mxCell>
- <mxCell id="EFqebEYhPqh4IJWovyJC-6" value="Puzzle module 1&lt;br&gt;(software)" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="EFqebEYhPqh4IJWovyJC-6" value="software puzzle module" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry x="200" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="EFqebEYhPqh4IJWovyJC-9" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;startArrow=classic;startFill=1;fontFamily=Arial;" parent="1" source="EFqebEYhPqh4IJWovyJC-7" target="EFqebEYhPqh4IJWovyJC-1" edge="1">
@@ -272,7 +272,7 @@
</Array>
</mxGeometry>
</mxCell>
- <mxCell id="EFqebEYhPqh4IJWovyJC-7" value="Puzzle module 2&lt;br style=&quot;border-color: var(--border-color);&quot;&gt;(hardware)" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="EFqebEYhPqh4IJWovyJC-7" value="hardware puzzle module" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry x="320" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="EFqebEYhPqh4IJWovyJC-13" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;" parent="1" source="EFqebEYhPqh4IJWovyJC-12" target="EFqebEYhPqh4IJWovyJC-1" edge="1">
@@ -283,19 +283,19 @@
</Array>
</mxGeometry>
</mxCell>
- <mxCell id="EFqebEYhPqh4IJWovyJC-12" value="Power supply&lt;br&gt;(battery pack)" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="EFqebEYhPqh4IJWovyJC-12" value="power supply&lt;br&gt;(battery pack)" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry x="80" y="160" width="80" height="80" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="h3DvyZ0KajeRp1tPME5F" name="system-top">
- <mxGraphModel dx="1422" dy="822" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+ <mxGraphModel dx="566" dy="347" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
- <mxCell id="nQz1uFQE7kBfjPpRPLva-4" value="Puzzle outputs" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;spacing=8;fontFamily=Arial;" parent="1" source="nQz1uFQE7kBfjPpRPLva-1" target="nQz1uFQE7kBfjPpRPLva-3" edge="1">
- <mxGeometry x="-0.8049" y="-20" relative="1" as="geometry">
+ <mxCell id="nQz1uFQE7kBfjPpRPLva-4" value="puzzle outputs" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;spacing=8;fontFamily=Arial;" parent="1" source="nQz1uFQE7kBfjPpRPLva-1" target="nQz1uFQE7kBfjPpRPLva-3" edge="1">
+ <mxGeometry x="-0.8054" y="-20" relative="1" as="geometry">
<Array as="points">
<mxPoint x="230" y="110" />
<mxPoint x="230" y="30" />
@@ -311,10 +311,10 @@
</Array>
</mxGeometry>
</mxCell>
- <mxCell id="nQz1uFQE7kBfjPpRPLva-1" value="Puzzle box" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="nQz1uFQE7kBfjPpRPLva-1" value="puzzle box" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry x="110" y="90" width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="nQz1uFQE7kBfjPpRPLva-2" value="Puzzle inputs" style="endArrow=classic;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;elbow=vertical;labelPosition=left;verticalLabelPosition=middle;align=right;verticalAlign=middle;spacing=8;fontFamily=Arial;" parent="1" source="nQz1uFQE7kBfjPpRPLva-3" target="nQz1uFQE7kBfjPpRPLva-1" edge="1">
+ <mxCell id="nQz1uFQE7kBfjPpRPLva-2" value="puzzle inputs" style="endArrow=classic;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;elbow=vertical;labelPosition=left;verticalLabelPosition=middle;align=right;verticalAlign=middle;spacing=8;fontFamily=Arial;" parent="1" source="nQz1uFQE7kBfjPpRPLva-3" target="nQz1uFQE7kBfjPpRPLva-1" edge="1">
<mxGeometry x="0.6098" width="50" height="50" relative="1" as="geometry">
<mxPoint x="70" y="110" as="sourcePoint" />
<mxPoint x="120" y="130" as="targetPoint" />
@@ -325,10 +325,10 @@
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
- <mxCell id="nQz1uFQE7kBfjPpRPLva-3" value="Player(s)" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="nQz1uFQE7kBfjPpRPLva-3" value="player(s)" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry x="135" width="30" height="60" as="geometry" />
</mxCell>
- <mxCell id="nQz1uFQE7kBfjPpRPLva-6" value="Charger" style="endArrow=classic;html=1;rounded=0;edgeStyle=elbowEdgeStyle;elbow=vertical;labelPosition=left;verticalLabelPosition=middle;align=right;verticalAlign=middle;dashed=1;spacing=8;fontFamily=Arial;" parent="1" target="nQz1uFQE7kBfjPpRPLva-1" edge="1">
+ <mxCell id="nQz1uFQE7kBfjPpRPLva-6" value="charger" style="endArrow=classic;html=1;rounded=0;edgeStyle=elbowEdgeStyle;elbow=vertical;labelPosition=left;verticalLabelPosition=middle;align=right;verticalAlign=middle;dashed=1;spacing=8;fontFamily=Arial;" parent="1" target="nQz1uFQE7kBfjPpRPLva-1" edge="1">
<mxGeometry x="-1" width="50" height="50" relative="1" as="geometry">
<mxPoint x="70" y="150" as="sourcePoint" />
<mxPoint x="90" y="150.2" as="targetPoint" />
@@ -342,32 +342,32 @@
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
- <mxCell id="rSJYnGe5hIWkDpeJhH4a-5" value="Bomb" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="rSJYnGe5hIWkDpeJhH4a-5" value="bomb" style="rounded=0;whiteSpace=wrap;html=1;dashed=1;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry x="310" y="90" width="80" height="80" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="V5677hnVqFOUu4LEfIlK" name="main-controller-top">
- <mxGraphModel dx="1422" dy="822" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+ <mxGraphModel dx="673" dy="413" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
- <mxCell id="E0vY4Tb27X8IZZSuRO_E-1" value="Main controller" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
- <mxGeometry x="70" y="60" width="80" height="80" as="geometry" />
+ <mxCell id="E0vY4Tb27X8IZZSuRO_E-1" value="main controller" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxGeometry x="70" y="40" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="E0vY4Tb27X8IZZSuRO_E-2" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fontFamily=Arial;" parent="1" source="_QeJvxVuYCE5Bx7Zj5Sh-1" target="E0vY4Tb27X8IZZSuRO_E-1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
- <mxPoint x="110" y="190" as="sourcePoint" />
- <mxPoint x="140" y="110" as="targetPoint" />
+ <mxPoint x="110" y="170" as="sourcePoint" />
+ <mxPoint x="140" y="90" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="_QeJvxVuYCE5Bx7Zj5Sh-1" value="Puzzle bus" style="line;strokeWidth=4;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;align=right;labelPosition=left;verticalLabelPosition=middle;verticalAlign=middle;spacingTop=0;spacing=8;fontFamily=Arial;" parent="1" vertex="1">
- <mxGeometry x="70" y="170" width="80" height="20" as="geometry" />
+ <mxCell id="_QeJvxVuYCE5Bx7Zj5Sh-1" value="puzzle bus" style="line;strokeWidth=4;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;align=right;labelPosition=left;verticalLabelPosition=middle;verticalAlign=middle;spacingTop=0;spacing=8;fontFamily=Arial;" parent="1" vertex="1">
+ <mxGeometry x="70" y="150" width="80" height="20" as="geometry" />
</mxCell>
<mxCell id="eXW24AF1M1Q80XVxQB3d-1" value="Wi-Fi" style="shape=link;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;labelPosition=center;verticalLabelPosition=top;align=center;verticalAlign=bottom;fontFamily=Arial;" parent="1" source="E0vY4Tb27X8IZZSuRO_E-1" edge="1">
<mxGeometry x="1" width="100" relative="1" as="geometry">
- <mxPoint x="160" y="30" as="sourcePoint" />
+ <mxPoint x="160" y="10" as="sourcePoint" />
<mxPoint x="110" y="20" as="targetPoint" />
<mxPoint as="offset" />
</mxGeometry>
@@ -376,33 +376,33 @@
</mxGraphModel>
</diagram>
<diagram name="puzzle-module-top" id="5pAH2Yn7Y32GPKnI9U_5">
- <mxGraphModel dx="1422" dy="822" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+ <mxGraphModel dx="566" dy="347" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="BVMe8izj958RTkFm3z60-0" />
<mxCell id="BVMe8izj958RTkFm3z60-1" parent="BVMe8izj958RTkFm3z60-0" />
- <mxCell id="BVMe8izj958RTkFm3z60-2" value="Puzzle module" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="BVMe8izj958RTkFm3z60-1" vertex="1">
- <mxGeometry x="120" y="10" width="80" height="80" as="geometry" />
+ <mxCell id="BVMe8izj958RTkFm3z60-2" value="puzzle module" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="BVMe8izj958RTkFm3z60-1" vertex="1">
+ <mxGeometry x="120" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="BVMe8izj958RTkFm3z60-3" value="" style="endArrow=classic;startArrow=classic;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fontFamily=Arial;" parent="BVMe8izj958RTkFm3z60-1" source="BVMe8izj958RTkFm3z60-4" target="BVMe8izj958RTkFm3z60-2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
- <mxPoint x="160" y="140" as="sourcePoint" />
- <mxPoint x="190" y="60" as="targetPoint" />
+ <mxPoint x="160" y="130" as="sourcePoint" />
+ <mxPoint x="190" y="50" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="BVMe8izj958RTkFm3z60-4" value="Puzzle bus" style="line;strokeWidth=4;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;align=right;labelPosition=left;verticalLabelPosition=middle;verticalAlign=middle;spacingTop=0;spacing=8;fontFamily=Arial;" parent="BVMe8izj958RTkFm3z60-1" vertex="1">
- <mxGeometry x="120" y="120" width="80" height="20" as="geometry" />
+ <mxCell id="BVMe8izj958RTkFm3z60-4" value="puzzle bus" style="line;strokeWidth=4;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;align=right;labelPosition=left;verticalLabelPosition=middle;verticalAlign=middle;spacingTop=0;spacing=8;fontFamily=Arial;" parent="BVMe8izj958RTkFm3z60-1" vertex="1">
+ <mxGeometry x="120" y="110" width="80" height="20" as="geometry" />
</mxCell>
- <mxCell id="tTlcU9ZqAkPjyI4FRPs--0" value="Puzzle outputs" style="endArrow=classic;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;spacing=8;fontFamily=Arial;" parent="BVMe8izj958RTkFm3z60-1" source="BVMe8izj958RTkFm3z60-2" edge="1">
+ <mxCell id="tTlcU9ZqAkPjyI4FRPs--0" value="puzzle outputs" style="endArrow=classic;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;spacing=8;fontFamily=Arial;" parent="BVMe8izj958RTkFm3z60-1" source="BVMe8izj958RTkFm3z60-2" edge="1">
<mxGeometry x="1" width="50" height="50" relative="1" as="geometry">
- <mxPoint x="150" y="130" as="sourcePoint" />
- <mxPoint x="240" y="50" as="targetPoint" />
+ <mxPoint x="150" y="120" as="sourcePoint" />
+ <mxPoint x="240" y="40" as="targetPoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
- <mxCell id="tTlcU9ZqAkPjyI4FRPs--1" value="Puzzle inputs" style="endArrow=classic;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;labelPosition=left;verticalLabelPosition=middle;align=right;verticalAlign=middle;spacing=8;fontFamily=Arial;" parent="BVMe8izj958RTkFm3z60-1" target="BVMe8izj958RTkFm3z60-2" edge="1">
+ <mxCell id="tTlcU9ZqAkPjyI4FRPs--1" value="puzzle inputs" style="endArrow=classic;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;labelPosition=left;verticalLabelPosition=middle;align=right;verticalAlign=middle;spacing=8;fontFamily=Arial;" parent="BVMe8izj958RTkFm3z60-1" target="BVMe8izj958RTkFm3z60-2" edge="1">
<mxGeometry x="-1" width="50" height="50" relative="1" as="geometry">
- <mxPoint x="80" y="50" as="sourcePoint" />
- <mxPoint x="270" y="60" as="targetPoint" />
+ <mxPoint x="80" y="40" as="sourcePoint" />
+ <mxPoint x="270" y="50" as="targetPoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
@@ -410,26 +410,26 @@
</mxGraphModel>
</diagram>
<diagram name="power-supply-top" id="OyUTR4VJhJkLCMkp9sBg">
- <mxGraphModel dx="1422" dy="822" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+ <mxGraphModel dx="471" dy="289" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="JhLPvhhKfH0WU0wtARFb-0" />
<mxCell id="JhLPvhhKfH0WU0wtARFb-1" parent="JhLPvhhKfH0WU0wtARFb-0" />
- <mxCell id="JhLPvhhKfH0WU0wtARFb-2" value="Power supply" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="JhLPvhhKfH0WU0wtARFb-1" vertex="1">
- <mxGeometry x="120" y="10" width="80" height="80" as="geometry" />
+ <mxCell id="JhLPvhhKfH0WU0wtARFb-2" value="power supply" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="JhLPvhhKfH0WU0wtARFb-1" vertex="1">
+ <mxGeometry x="90" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="JhLPvhhKfH0WU0wtARFb-3" value="" style="endArrow=none;startArrow=classic;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fontFamily=Arial;endFill=0;" parent="JhLPvhhKfH0WU0wtARFb-1" source="JhLPvhhKfH0WU0wtARFb-4" target="JhLPvhhKfH0WU0wtARFb-2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
- <mxPoint x="160" y="140" as="sourcePoint" />
- <mxPoint x="190" y="60" as="targetPoint" />
+ <mxPoint x="130" y="130" as="sourcePoint" />
+ <mxPoint x="160" y="50" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="JhLPvhhKfH0WU0wtARFb-4" value="Puzzle bus" style="line;strokeWidth=4;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;align=right;labelPosition=left;verticalLabelPosition=middle;verticalAlign=middle;spacingTop=0;spacing=8;fontFamily=Arial;" parent="JhLPvhhKfH0WU0wtARFb-1" vertex="1">
- <mxGeometry x="120" y="120" width="80" height="20" as="geometry" />
+ <mxCell id="JhLPvhhKfH0WU0wtARFb-4" value="puzzle bus" style="line;strokeWidth=4;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;align=right;labelPosition=left;verticalLabelPosition=middle;verticalAlign=middle;spacingTop=0;spacing=8;fontFamily=Arial;" parent="JhLPvhhKfH0WU0wtARFb-1" vertex="1">
+ <mxGeometry x="90" y="110" width="80" height="20" as="geometry" />
</mxCell>
- <mxCell id="G88CfNIh1Ql9ssuBFCwE-0" value="Charger" style="endArrow=classic;html=1;rounded=0;edgeStyle=elbowEdgeStyle;elbow=vertical;labelPosition=left;verticalLabelPosition=middle;align=right;verticalAlign=middle;dashed=1;spacing=8;fontFamily=Arial;" parent="JhLPvhhKfH0WU0wtARFb-1" target="JhLPvhhKfH0WU0wtARFb-2" edge="1">
+ <mxCell id="G88CfNIh1Ql9ssuBFCwE-0" value="charger" style="endArrow=classic;html=1;rounded=0;edgeStyle=elbowEdgeStyle;elbow=vertical;labelPosition=left;verticalLabelPosition=middle;align=right;verticalAlign=middle;dashed=1;spacing=8;fontFamily=Arial;" parent="JhLPvhhKfH0WU0wtARFb-1" target="JhLPvhhKfH0WU0wtARFb-2" edge="1">
<mxGeometry x="-1" width="50" height="50" relative="1" as="geometry">
- <mxPoint x="80" y="50" as="sourcePoint" />
- <mxPoint x="110" y="150" as="targetPoint" />
+ <mxPoint x="50" y="40" as="sourcePoint" />
+ <mxPoint x="80" y="140" as="targetPoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
@@ -437,465 +437,249 @@
</mxGraphModel>
</diagram>
<diagram id="tQJt-i1klPodeKevl6yF" name="puzzle-module-common-state">
- <mxGraphModel dx="1422" dy="822" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+ <mxGraphModel dx="673" dy="413" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
- <mxCell id="5xofdATqJuVrBNkdsEzn-2" value="Uninitialized" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxCell id="mQ-fNEReojakqp_WspgU-2" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;" edge="1" parent="1" source="5xofdATqJuVrBNkdsEzn-2" target="5xofdATqJuVrBNkdsEzn-3">
+ <mxGeometry relative="1" as="geometry" />
+ </mxCell>
+ <mxCell id="5xofdATqJuVrBNkdsEzn-2" value="uninitialized" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
<mxGeometry width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="5xofdATqJuVrBNkdsEzn-6" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;" parent="1" source="5xofdATqJuVrBNkdsEzn-3" target="5xofdATqJuVrBNkdsEzn-4" edge="1">
+ <mxCell id="5xofdATqJuVrBNkdsEzn-6" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;dashed=1;" parent="1" source="5xofdATqJuVrBNkdsEzn-3" target="5xofdATqJuVrBNkdsEzn-4" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
- <mxCell id="5xofdATqJuVrBNkdsEzn-3" value="Reset" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
- <mxGeometry x="100" width="60" height="60" as="geometry" />
+ <mxCell id="5xofdATqJuVrBNkdsEzn-3" value="idle" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxGeometry x="100" width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="5xofdATqJuVrBNkdsEzn-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;" parent="1" source="5xofdATqJuVrBNkdsEzn-4" target="5xofdATqJuVrBNkdsEzn-5" edge="1">
+ <mxCell id="5xofdATqJuVrBNkdsEzn-7" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;" parent="1" source="5xofdATqJuVrBNkdsEzn-4" target="5xofdATqJuVrBNkdsEzn-5" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
- <mxCell id="5xofdATqJuVrBNkdsEzn-4" value="Playing" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
- <mxGeometry x="100" y="80" width="60" height="60" as="geometry" />
+ <mxCell id="5xofdATqJuVrBNkdsEzn-4" value="playing" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxGeometry x="200" width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="5xofdATqJuVrBNkdsEzn-5" value="Solved" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
- <mxGeometry x="100" y="160" width="60" height="60" as="geometry" />
+ <mxCell id="5xofdATqJuVrBNkdsEzn-5" value="solved" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxGeometry x="300" width="80" height="80" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="3POUz5nivpBRA6uf3okY" name="main-controller-state">
- <mxGraphModel dx="1434" dy="854" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
+ <mxGraphModel dx="673" dy="413" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
- <mxCell id="7O8kuJQz2iaT31b0g9wK-1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;curved=1;" parent="1" source="7O8kuJQz2iaT31b0g9wK-2" target="7O8kuJQz2iaT31b0g9wK-4" edge="1">
- <mxGeometry relative="1" as="geometry">
- <Array as="points">
- <mxPoint x="70" y="60" />
- </Array>
- </mxGeometry>
- </mxCell>
- <mxCell id="7O8kuJQz2iaT31b0g9wK-2" value="Reset" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
- <mxGeometry width="60" height="60" as="geometry" />
- </mxCell>
- <mxCell id="7O8kuJQz2iaT31b0g9wK-4" value="Playing" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
- <mxGeometry x="80" width="60" height="60" as="geometry" />
- </mxCell>
- <mxCell id="7O8kuJQz2iaT31b0g9wK-5" value="Solved" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
- <mxGeometry x="160" width="60" height="60" as="geometry" />
- </mxCell>
- <mxCell id="7O8kuJQz2iaT31b0g9wK-6" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;curved=1;" parent="1" source="7O8kuJQz2iaT31b0g9wK-4" target="7O8kuJQz2iaT31b0g9wK-2" edge="1">
- <mxGeometry relative="1" as="geometry">
- <mxPoint x="55" y="66" as="sourcePoint" />
- <mxPoint x="55" y="114" as="targetPoint" />
- <Array as="points">
- <mxPoint x="70" />
- </Array>
- </mxGeometry>
- </mxCell>
- <mxCell id="7O8kuJQz2iaT31b0g9wK-7" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;curved=1;" parent="1" source="7O8kuJQz2iaT31b0g9wK-4" target="7O8kuJQz2iaT31b0g9wK-5" edge="1">
- <mxGeometry relative="1" as="geometry">
- <mxPoint x="45" y="140" as="sourcePoint" />
- <mxPoint x="45" y="188" as="targetPoint" />
- <Array as="points">
- <mxPoint x="150" y="60" />
- </Array>
- </mxGeometry>
- </mxCell>
- <mxCell id="7O8kuJQz2iaT31b0g9wK-8" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;curved=1;" parent="1" source="7O8kuJQz2iaT31b0g9wK-5" target="7O8kuJQz2iaT31b0g9wK-4" edge="1">
+ <mxCell id="7O8kuJQz2iaT31b0g9wK-1" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;curved=1;dashed=1;" parent="1" source="7O8kuJQz2iaT31b0g9wK-2" target="7O8kuJQz2iaT31b0g9wK-4" edge="1">
<mxGeometry relative="1" as="geometry">
- <mxPoint x="15" y="188" as="sourcePoint" />
- <mxPoint x="15" y="140" as="targetPoint" />
<Array as="points">
- <mxPoint x="150" />
+ <mxPoint x="90" y="70" />
</Array>
</mxGeometry>
</mxCell>
- </root>
- </mxGraphModel>
- </diagram>
- <diagram id="Rp6IhanA7F14BRU2Iihj" name="sequence-puzzle-module-init">
- <mxGraphModel dx="683" dy="407" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
- <root>
- <mxCell id="0" />
- <mxCell id="1" parent="0" />
- <mxCell id="FgPCU9YjluK7leEd9PPU-4" value="Main" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;elbow&quot;:&quot;vertical&quot;,&quot;curved&quot;:0,&quot;rounded&quot;:0};size=20;fontFamily=Arial;" parent="1" vertex="1">
- <mxGeometry x="20" width="40" height="150" as="geometry" />
- </mxCell>
- <mxCell id="FgPCU9YjluK7leEd9PPU-9" value="" style="html=1;points=[[0,0,0,0,5],[0,1,0,0,-5],[1,0,0,0,5],[1,1,0,0,-5]];perimeter=orthogonalPerimeter;outlineConnect=0;targetShapes=umlLifeline;portConstraint=eastwest;newEdgeStyle={&quot;curved&quot;:0,&quot;rounded&quot;:0};fontFamily=Arial;" parent="FgPCU9YjluK7leEd9PPU-4" vertex="1">
- <mxGeometry x="15" y="50" width="10" height="100" as="geometry" />
- </mxCell>
- <mxCell id="FgPCU9YjluK7leEd9PPU-11" value="update" style="edgeStyle=elbowEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;elbow=vertical;fontFamily=Arial;" parent="1" source="FgPCU9YjluK7leEd9PPU-5" target="FgPCU9YjluK7leEd9PPU-9" edge="1">
- <mxGeometry relative="1" as="geometry">
- <Array as="points">
- <mxPoint x="120" y="70" />
- <mxPoint x="80" y="60" />
- </Array>
- </mxGeometry>
- </mxCell>
- <mxCell id="FgPCU9YjluK7leEd9PPU-5" value="A" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;elbow&quot;:&quot;vertical&quot;,&quot;curved&quot;:0,&quot;rounded&quot;:0};size=20;fontFamily=Arial;" parent="1" vertex="1">
- <mxGeometry x="130" width="20" height="150" as="geometry" />
- </mxCell>
- <mxCell id="FgPCU9YjluK7leEd9PPU-10" value="" style="html=1;points=[[0,0,0,0,5],[0,1,0,0,-5],[1,0,0,0,5],[1,1,0,0,-5]];perimeter=orthogonalPerimeter;outlineConnect=0;targetShapes=umlLifeline;portConstraint=eastwest;newEdgeStyle={&quot;curved&quot;:0,&quot;rounded&quot;:0};fontFamily=Arial;" parent="FgPCU9YjluK7leEd9PPU-5" vertex="1">
- <mxGeometry x="5" y="130" width="10" height="20" as="geometry" />
- </mxCell>
- <mxCell id="AQniHDs8FXXc9mSBzi3H-1" value="state := reset" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;elbow=vertical;fontFamily=Arial;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;" edge="1" parent="FgPCU9YjluK7leEd9PPU-5" source="FgPCU9YjluK7leEd9PPU-5" target="FgPCU9YjluK7leEd9PPU-10">
- <mxGeometry x="0.8571" y="-10" relative="1" as="geometry">
- <mxPoint x="40" y="110" as="sourcePoint" />
- <mxPoint x="40" y="130" as="targetPoint" />
- <Array as="points">
- <mxPoint x="40" y="110" />
- <mxPoint x="40" y="130" />
- </Array>
- <mxPoint as="offset" />
- </mxGeometry>
- </mxCell>
- <mxCell id="FgPCU9YjluK7leEd9PPU-12" value="state := reset" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;curved=0;fontFamily=Arial;" parent="1" source="FgPCU9YjluK7leEd9PPU-9" target="FgPCU9YjluK7leEd9PPU-5" edge="1">
- <mxGeometry relative="1" as="geometry">
- <Array as="points">
- <mxPoint x="90" y="90" />
- <mxPoint x="90" y="90" />
- </Array>
- </mxGeometry>
- </mxCell>
- <mxCell id="FgPCU9YjluK7leEd9PPU-13" value="power on" style="endArrow=none;html=1;endSize=12;startArrow=none;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=right;verticalAlign=bottom;endFill=0;rounded=0;labelPosition=left;verticalLabelPosition=top;fontFamily=Arial;dashed=1;" parent="1" edge="1">
- <mxGeometry x="1" relative="1" as="geometry">
- <mxPoint y="50" as="sourcePoint" />
- <mxPoint x="200" y="50" as="targetPoint" />
- <mxPoint as="offset" />
- </mxGeometry>
- </mxCell>
- <mxCell id="Yg9NV-g9DN27sBcjv-cp-1" value="update" style="edgeStyle=elbowEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;elbow=vertical;fontFamily=Arial;" edge="1" parent="1" source="FgPCU9YjluK7leEd9PPU-10" target="FgPCU9YjluK7leEd9PPU-9">
- <mxGeometry relative="1" as="geometry">
- <Array as="points">
- <mxPoint x="120" y="140" />
- <mxPoint x="80" y="110" />
- </Array>
- <mxPoint x="140" y="120" as="sourcePoint" />
- <mxPoint x="45" y="120" as="targetPoint" />
- </mxGeometry>
- </mxCell>
- </root>
- </mxGraphModel>
- </diagram>
- <diagram name="sequence-puzzle-finish" id="c22ujPTqKurZEIIZxMnS">
- <mxGraphModel dx="989" dy="589" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
- <root>
- <mxCell id="Zx0YANjdZ0Bqq7mGd-Li-0" />
- <mxCell id="Zx0YANjdZ0Bqq7mGd-Li-1" parent="Zx0YANjdZ0Bqq7mGd-Li-0" />
- <mxCell id="Zx0YANjdZ0Bqq7mGd-Li-2" value="Main" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;elbow&quot;:&quot;vertical&quot;,&quot;curved&quot;:0,&quot;rounded&quot;:0};size=20;fontFamily=Arial;" parent="Zx0YANjdZ0Bqq7mGd-Li-1" vertex="1">
- <mxGeometry x="20" width="40" height="320" as="geometry" />
- </mxCell>
- <mxCell id="Zx0YANjdZ0Bqq7mGd-Li-3" value="" style="html=1;points=[[0,0,0,0,5],[0,1,0,0,-5],[1,0,0,0,5],[1,1,0,0,-5]];perimeter=orthogonalPerimeter;outlineConnect=0;targetShapes=umlLifeline;portConstraint=eastwest;newEdgeStyle={&quot;curved&quot;:0,&quot;rounded&quot;:0};fontFamily=Arial;" parent="Zx0YANjdZ0Bqq7mGd-Li-2" vertex="1">
- <mxGeometry x="15" y="30" width="10" height="290" as="geometry" />
- </mxCell>
- <mxCell id="mC0UOUuOwT6DkYXV2a_g-6" value="state := solved" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;elbow=vertical;fontFamily=Arial;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;" parent="Zx0YANjdZ0Bqq7mGd-Li-2" source="Zx0YANjdZ0Bqq7mGd-Li-3" target="Zx0YANjdZ0Bqq7mGd-Li-3" edge="1">
- <mxGeometry x="0.8571" y="-10" relative="1" as="geometry">
- <mxPoint x="25" y="130" as="sourcePoint" />
- <mxPoint x="25" y="150" as="targetPoint" />
- <Array as="points">
- <mxPoint x="50" y="180" />
- <mxPoint x="50" y="200" />
- </Array>
- <mxPoint as="offset" />
- </mxGeometry>
- </mxCell>
- <mxCell id="Zx0YANjdZ0Bqq7mGd-Li-5" value="A" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;elbow&quot;:&quot;vertical&quot;,&quot;curved&quot;:0,&quot;rounded&quot;:0};size=20;fontFamily=Arial;" parent="Zx0YANjdZ0Bqq7mGd-Li-1" vertex="1">
- <mxGeometry x="130" width="20" height="320" as="geometry" />
- </mxCell>
- <mxCell id="Zx0YANjdZ0Bqq7mGd-Li-6" value="" style="html=1;points=[[0,0,0,0,5],[0,1,0,0,-5],[1,0,0,0,5],[1,1,0,0,-5]];perimeter=orthogonalPerimeter;outlineConnect=0;targetShapes=umlLifeline;portConstraint=eastwest;newEdgeStyle={&quot;curved&quot;:0,&quot;rounded&quot;:0};fontFamily=Arial;" parent="Zx0YANjdZ0Bqq7mGd-Li-5" vertex="1">
- <mxGeometry x="5" y="30" width="10" height="290" as="geometry" />
- </mxCell>
- <mxCell id="mC0UOUuOwT6DkYXV2a_g-1" value="state := solved" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;elbow=vertical;fontFamily=Arial;labelPosition=right;verticalLabelPosition=middle;align=left;verticalAlign=middle;" parent="Zx0YANjdZ0Bqq7mGd-Li-5" source="Zx0YANjdZ0Bqq7mGd-Li-6" target="Zx0YANjdZ0Bqq7mGd-Li-6" edge="1">
- <mxGeometry x="0.8571" y="-10" relative="1" as="geometry">
- <mxPoint x="40" y="60" as="sourcePoint" />
- <mxPoint x="15" y="60" as="targetPoint" />
- <Array as="points">
- <mxPoint x="40" y="50" />
- <mxPoint x="40" y="70" />
- </Array>
- <mxPoint as="offset" />
- </mxGeometry>
- </mxCell>
- <mxCell id="p1oUzKR6Frcw5nPdyHcq-0" value="B" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;dropTarget=0;collapsible=0;recursiveResize=0;outlineConnect=0;portConstraint=eastwest;newEdgeStyle={&quot;edgeStyle&quot;:&quot;elbowEdgeStyle&quot;,&quot;elbow&quot;:&quot;vertical&quot;,&quot;curved&quot;:0,&quot;rounded&quot;:0};size=20;fontFamily=Arial;" parent="Zx0YANjdZ0Bqq7mGd-Li-1" vertex="1">
- <mxGeometry x="230" width="20" height="320" as="geometry" />
- </mxCell>
- <mxCell id="p1oUzKR6Frcw5nPdyHcq-1" value="" style="html=1;points=[[0,0,0,0,5],[0,1,0,0,-5],[1,0,0,0,5],[1,1,0,0,-5]];perimeter=orthogonalPerimeter;outlineConnect=0;targetShapes=umlLifeline;portConstraint=eastwest;newEdgeStyle={&quot;curved&quot;:0,&quot;rounded&quot;:0};fontFamily=Arial;" parent="p1oUzKR6Frcw5nPdyHcq-0" vertex="1">
- <mxGeometry x="5" y="30" width="10" height="290" as="geometry" />
- </mxCell>
- <mxCell id="mC0UOUuOwT6DkYXV2a_g-2" value="update" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;elbow=vertical;fontFamily=Arial;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;" parent="Zx0YANjdZ0Bqq7mGd-Li-1" source="Zx0YANjdZ0Bqq7mGd-Li-6" target="Zx0YANjdZ0Bqq7mGd-Li-3" edge="1">
- <mxGeometry relative="1" as="geometry">
- <mxPoint x="155" y="45" as="sourcePoint" />
- <mxPoint x="155" y="70" as="targetPoint" />
- <Array as="points">
- <mxPoint x="90" y="80" />
- <mxPoint x="90" y="80" />
- </Array>
- <mxPoint as="offset" />
- </mxGeometry>
- </mxCell>
- <mxCell id="mC0UOUuOwT6DkYXV2a_g-3" value="update" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;elbow=vertical;fontFamily=Arial;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;" parent="Zx0YANjdZ0Bqq7mGd-Li-1" source="Zx0YANjdZ0Bqq7mGd-Li-3" target="p1oUzKR6Frcw5nPdyHcq-1" edge="1">
- <mxGeometry x="-0.5263" relative="1" as="geometry">
- <mxPoint x="45" y="190" as="sourcePoint" />
- <mxPoint x="235" y="190" as="targetPoint" />
- <Array as="points">
- <mxPoint x="130" y="240" />
- <mxPoint x="130" y="240" />
- </Array>
- <mxPoint as="offset" />
- </mxGeometry>
+ <mxCell id="7O8kuJQz2iaT31b0g9wK-2" value="idle" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxGeometry width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="mC0UOUuOwT6DkYXV2a_g-4" value="main state?" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;elbow=vertical;fontFamily=Arial;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;" parent="Zx0YANjdZ0Bqq7mGd-Li-1" source="p1oUzKR6Frcw5nPdyHcq-1" target="Zx0YANjdZ0Bqq7mGd-Li-3" edge="1">
- <mxGeometry x="-0.5263" relative="1" as="geometry">
- <mxPoint x="235" y="210" as="sourcePoint" />
- <mxPoint x="45" y="210" as="targetPoint" />
- <Array as="points">
- <mxPoint x="130" y="280" />
- <mxPoint x="130" y="280" />
- </Array>
- <mxPoint as="offset" />
- </mxGeometry>
+ <mxCell id="7O8kuJQz2iaT31b0g9wK-4" value="playing" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxGeometry x="100" width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="mC0UOUuOwT6DkYXV2a_g-5" value="= solved" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;elbow=vertical;fontFamily=Arial;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;" parent="Zx0YANjdZ0Bqq7mGd-Li-1" source="Zx0YANjdZ0Bqq7mGd-Li-3" target="p1oUzKR6Frcw5nPdyHcq-1" edge="1">
- <mxGeometry x="0.5263" relative="1" as="geometry">
- <mxPoint x="45" y="230" as="sourcePoint" />
- <mxPoint x="235" y="230" as="targetPoint" />
- <Array as="points">
- <mxPoint x="130" y="300" />
- <mxPoint x="130" y="300" />
- </Array>
- <mxPoint as="offset" />
- </mxGeometry>
+ <mxCell id="7O8kuJQz2iaT31b0g9wK-5" value="solved" style="ellipse;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="1" vertex="1">
+ <mxGeometry x="200" width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="mC0UOUuOwT6DkYXV2a_g-7" value="update" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;elbow=vertical;fontFamily=Arial;labelPosition=center;verticalLabelPosition=middle;align=center;verticalAlign=middle;" parent="Zx0YANjdZ0Bqq7mGd-Li-1" source="Zx0YANjdZ0Bqq7mGd-Li-3" target="Zx0YANjdZ0Bqq7mGd-Li-6" edge="1">
+ <mxCell id="7O8kuJQz2iaT31b0g9wK-6" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;curved=1;dashed=1;" parent="1" source="7O8kuJQz2iaT31b0g9wK-4" target="7O8kuJQz2iaT31b0g9wK-2" edge="1">
<mxGeometry relative="1" as="geometry">
- <mxPoint x="45" y="170" as="sourcePoint" />
- <mxPoint x="135" y="170" as="targetPoint" />
+ <mxPoint x="85" y="76" as="sourcePoint" />
+ <mxPoint x="85" y="124" as="targetPoint" />
<Array as="points">
- <mxPoint x="90" y="220" />
- <mxPoint x="90" y="220" />
+ <mxPoint x="90" y="10" />
</Array>
- <mxPoint as="offset" />
</mxGeometry>
</mxCell>
- <mxCell id="WlnYjSTvFQ-Kx6sK1-3f-0" value="state?" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;curved=0;fontFamily=Arial;" edge="1" parent="Zx0YANjdZ0Bqq7mGd-Li-1" source="Zx0YANjdZ0Bqq7mGd-Li-3" target="Zx0YANjdZ0Bqq7mGd-Li-6">
+ <mxCell id="7O8kuJQz2iaT31b0g9wK-7" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;curved=1;dashed=1;" parent="1" source="7O8kuJQz2iaT31b0g9wK-4" target="7O8kuJQz2iaT31b0g9wK-5" edge="1">
<mxGeometry relative="1" as="geometry">
+ <mxPoint x="75" y="150" as="sourcePoint" />
+ <mxPoint x="75" y="198" as="targetPoint" />
<Array as="points">
- <mxPoint x="90" y="120" />
- <mxPoint x="90" y="120" />
+ <mxPoint x="190" y="70" />
</Array>
</mxGeometry>
</mxCell>
- <mxCell id="WlnYjSTvFQ-Kx6sK1-3f-1" value="= solved" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;curved=0;fontFamily=Arial;" edge="1" parent="Zx0YANjdZ0Bqq7mGd-Li-1" source="Zx0YANjdZ0Bqq7mGd-Li-6" target="Zx0YANjdZ0Bqq7mGd-Li-3">
+ <mxCell id="7O8kuJQz2iaT31b0g9wK-8" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;fontFamily=Arial;curved=1;dashed=1;" parent="1" source="7O8kuJQz2iaT31b0g9wK-5" target="7O8kuJQz2iaT31b0g9wK-4" edge="1">
<mxGeometry relative="1" as="geometry">
+ <mxPoint x="45" y="198" as="sourcePoint" />
+ <mxPoint x="45" y="150" as="targetPoint" />
<Array as="points">
- <mxPoint x="90" y="140" />
- <mxPoint x="90" y="140" />
+ <mxPoint x="190" y="10" />
</Array>
</mxGeometry>
</mxCell>
- <mxCell id="K4EzKAKXCnabXeHCjeBN-0" value="" style="endArrow=none;dashed=1;html=1;rounded=0;fontFamily=Arial;" edge="1" parent="Zx0YANjdZ0Bqq7mGd-Li-1">
- <mxGeometry width="50" height="50" relative="1" as="geometry">
- <mxPoint x="10" y="30" as="sourcePoint" />
- <mxPoint x="260" y="30" as="targetPoint" />
- </mxGeometry>
- </mxCell>
- <mxCell id="K4EzKAKXCnabXeHCjeBN-1" value="" style="endArrow=none;dashed=1;html=1;rounded=0;fontFamily=Arial;" edge="1" parent="Zx0YANjdZ0Bqq7mGd-Li-1">
- <mxGeometry width="50" height="50" relative="1" as="geometry">
- <mxPoint x="10" y="100" as="sourcePoint" />
- <mxPoint x="260" y="100" as="targetPoint" />
- </mxGeometry>
- </mxCell>
- <mxCell id="K4EzKAKXCnabXeHCjeBN-2" value="" style="endArrow=none;dashed=1;html=1;rounded=0;fontFamily=Arial;" edge="1" parent="Zx0YANjdZ0Bqq7mGd-Li-1">
- <mxGeometry width="50" height="50" relative="1" as="geometry">
- <mxPoint x="10" y="159.82999999999998" as="sourcePoint" />
- <mxPoint x="260" y="159.82999999999998" as="targetPoint" />
- </mxGeometry>
- </mxCell>
- <mxCell id="K4EzKAKXCnabXeHCjeBN-3" value="" style="endArrow=none;dashed=1;html=1;rounded=0;fontFamily=Arial;" edge="1" parent="Zx0YANjdZ0Bqq7mGd-Li-1">
- <mxGeometry width="50" height="50" relative="1" as="geometry">
- <mxPoint x="10" y="260" as="sourcePoint" />
- <mxPoint x="260" y="260" as="targetPoint" />
- </mxGeometry>
- </mxCell>
- <mxCell id="K4EzKAKXCnabXeHCjeBN-4" value="1" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Arial;" vertex="1" parent="Zx0YANjdZ0Bqq7mGd-Li-1">
- <mxGeometry y="30" width="20" height="70" as="geometry" />
- </mxCell>
- <mxCell id="K4EzKAKXCnabXeHCjeBN-5" value="2" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Arial;" vertex="1" parent="Zx0YANjdZ0Bqq7mGd-Li-1">
- <mxGeometry y="100" width="20" height="60" as="geometry" />
- </mxCell>
- <mxCell id="K4EzKAKXCnabXeHCjeBN-6" value="3" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Arial;" vertex="1" parent="Zx0YANjdZ0Bqq7mGd-Li-1">
- <mxGeometry y="160" width="20" height="100" as="geometry" />
- </mxCell>
- <mxCell id="K4EzKAKXCnabXeHCjeBN-7" value="4" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontFamily=Arial;" vertex="1" parent="Zx0YANjdZ0Bqq7mGd-Li-1">
- <mxGeometry y="260" width="20" height="60" as="geometry" />
- </mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="nZD7urG06ZLRag7bfLhG" name="vault-puzzle-io">
- <mxGraphModel dx="1422" dy="822" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" math="0" shadow="0">
+ <mxGraphModel dx="1414" dy="867" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" math="0" shadow="0">
<root>
<mxCell id="7HM9CflW6hoJ5ROsD5Xs-0" />
<mxCell id="7HM9CflW6hoJ5ROsD5Xs-1" parent="7HM9CflW6hoJ5ROsD5Xs-0" />
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-2" value="[Vault puzzle module]&lt;br&gt;ESP32 PICO D4 Devkit" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-2" value="[Vault puzzle module]&lt;br&gt;ESP32 PICO D4 Devkit" style="rounded=0;whiteSpace=wrap;html=1;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="490" y="250" width="120" height="200" as="geometry" />
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-3" value="IN" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-3" value="IN" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="440" y="250" width="40" height="20" as="geometry" />
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-4" value="OUT" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-4" value="OUT" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="620" y="250" width="40" height="20" as="geometry" />
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-6" value="" style="endArrow=none;html=1;strokeWidth=3;" edge="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-6" value="" style="endArrow=none;html=1;strokeWidth=3;" parent="7HM9CflW6hoJ5ROsD5Xs-1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="280" y="560" as="sourcePoint" />
<mxPoint x="920" y="560" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-7" value="" style="endArrow=classic;startArrow=classic;html=1;strokeWidth=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="7HM9CflW6hoJ5ROsD5Xs-1" target="7HM9CflW6hoJ5ROsD5Xs-2">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-7" value="" style="endArrow=classic;startArrow=classic;html=1;strokeWidth=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" target="7HM9CflW6hoJ5ROsD5Xs-2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="550" y="560" as="sourcePoint" />
<mxPoint x="390" y="370" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-8" value="Puzzle bus&lt;br&gt;I²C + power" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-8" value="Puzzle bus&lt;br&gt;I²C + power" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="180" y="550" width="110" height="20" as="geometry" />
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-9" value="4x 7-SEG diplay package" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-9" value="4x 7-SEG diplay package" style="rounded=0;whiteSpace=wrap;html=1;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="780" y="240" width="120" height="60" as="geometry" />
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-10" value="Keypad" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-10" value="Keypad" style="rounded=0;whiteSpace=wrap;html=1;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="230" y="320" width="120" height="60" as="geometry" />
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-11" value="Solenoid lock" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-11" value="Solenoid lock" style="rounded=0;whiteSpace=wrap;html=1;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="780" y="320" width="120" height="60" as="geometry" />
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-12" value="Buzzer" style="rounded=0;whiteSpace=wrap;html=1;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-12" value="Buzzer" style="rounded=0;whiteSpace=wrap;html=1;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="780" y="400" width="120" height="60" as="geometry" />
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-13" value="" style="endArrow=classic;startArrow=none;html=1;strokeWidth=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;startFill=0;" edge="1" parent="7HM9CflW6hoJ5ROsD5Xs-1" source="7HM9CflW6hoJ5ROsD5Xs-10" target="7HM9CflW6hoJ5ROsD5Xs-2">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-13" value="" style="endArrow=classic;startArrow=none;html=1;strokeWidth=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;startFill=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" source="7HM9CflW6hoJ5ROsD5Xs-10" target="7HM9CflW6hoJ5ROsD5Xs-2" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="290" y="480" as="sourcePoint" />
<mxPoint x="340" y="430" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-14" value="" style="endArrow=classic;startArrow=none;html=1;strokeWidth=1;entryX=-0.008;entryY=0.617;entryDx=0;entryDy=0;entryPerimeter=0;exitX=1.025;exitY=0.535;exitDx=0;exitDy=0;exitPerimeter=0;startFill=0;" edge="1" parent="7HM9CflW6hoJ5ROsD5Xs-1" source="7HM9CflW6hoJ5ROsD5Xs-2" target="7HM9CflW6hoJ5ROsD5Xs-11">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-14" value="" style="endArrow=classic;startArrow=none;html=1;strokeWidth=1;entryX=-0.008;entryY=0.617;entryDx=0;entryDy=0;entryPerimeter=0;exitX=1.025;exitY=0.535;exitDx=0;exitDy=0;exitPerimeter=0;startFill=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" source="7HM9CflW6hoJ5ROsD5Xs-2" target="7HM9CflW6hoJ5ROsD5Xs-11" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="660" y="390" as="sourcePoint" />
<mxPoint x="710" y="340" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-15" value="" style="endArrow=classic;startArrow=none;html=1;strokeWidth=1;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1.025;exitY=0.175;exitDx=0;exitDy=0;exitPerimeter=0;startFill=0;" edge="1" parent="7HM9CflW6hoJ5ROsD5Xs-1" source="7HM9CflW6hoJ5ROsD5Xs-2" target="7HM9CflW6hoJ5ROsD5Xs-9">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-15" value="" style="endArrow=classic;startArrow=none;html=1;strokeWidth=1;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1.025;exitY=0.175;exitDx=0;exitDy=0;exitPerimeter=0;startFill=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" source="7HM9CflW6hoJ5ROsD5Xs-2" target="7HM9CflW6hoJ5ROsD5Xs-9" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="630" y="290" as="sourcePoint" />
<mxPoint x="710" y="420" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-16" value="" style="endArrow=classic;startArrow=none;html=1;strokeWidth=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;exitX=1.025;exitY=0.83;exitDx=0;exitDy=0;exitPerimeter=0;startFill=0;" edge="1" parent="7HM9CflW6hoJ5ROsD5Xs-1" source="7HM9CflW6hoJ5ROsD5Xs-2" target="7HM9CflW6hoJ5ROsD5Xs-12">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-16" value="" style="endArrow=classic;startArrow=none;html=1;strokeWidth=1;entryX=0;entryY=0.25;entryDx=0;entryDy=0;exitX=1.025;exitY=0.83;exitDx=0;exitDy=0;exitPerimeter=0;startFill=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" source="7HM9CflW6hoJ5ROsD5Xs-2" target="7HM9CflW6hoJ5ROsD5Xs-12" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="620" y="520" as="sourcePoint" />
<mxPoint x="670" y="470" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-18" value="" style="endArrow=none;html=1;strokeWidth=1;" edge="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-18" value="" style="endArrow=none;html=1;strokeWidth=1;" parent="7HM9CflW6hoJ5ROsD5Xs-1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="410" y="360" as="sourcePoint" />
<mxPoint x="420" y="340" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-22" value="" style="endArrow=none;html=1;strokeWidth=1;" edge="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-22" value="" style="endArrow=none;html=1;strokeWidth=1;" parent="7HM9CflW6hoJ5ROsD5Xs-1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="690" y="296" as="sourcePoint" />
<mxPoint x="700" y="276" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-23" value="5" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-23" value="5" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="400" y="310" width="40" height="20" as="geometry" />
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-24" value="2" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-24" value="2" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="680" y="250" width="40" height="20" as="geometry" />
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-27" value="" style="endArrow=none;html=1;strokeWidth=1;" edge="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-27" value="" style="endArrow=none;html=1;strokeWidth=1;" parent="7HM9CflW6hoJ5ROsD5Xs-1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="540" y="512" as="sourcePoint" />
<mxPoint x="560" y="492" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="7HM9CflW6hoJ5ROsD5Xs-28" value="2" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="7HM9CflW6hoJ5ROsD5Xs-1">
+ <mxCell id="7HM9CflW6hoJ5ROsD5Xs-28" value="2" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="7HM9CflW6hoJ5ROsD5Xs-1" vertex="1">
<mxGeometry x="550" y="490" width="40" height="20" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
<diagram id="7POXNBDTHuzmCPITFMB0" name="puzzlebox-bomb">
- <mxGraphModel dx="1422" dy="822" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" math="0" shadow="0">
+ <mxGraphModel dx="1414" dy="867" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" math="0" shadow="0">
<root>
<mxCell id="VDsyqYXPtuEwqBrCnzhW-0" />
<mxCell id="VDsyqYXPtuEwqBrCnzhW-1" parent="VDsyqYXPtuEwqBrCnzhW-0" />
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-0" value="Puzzlebox" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" vertex="1" parent="VDsyqYXPtuEwqBrCnzhW-1">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-0" value="Puzzlebox" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="VDsyqYXPtuEwqBrCnzhW-1" vertex="1">
<mxGeometry x="300" y="415" width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-3" value="Wi-Fi" style="shape=link;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;labelPosition=center;verticalLabelPosition=top;align=center;verticalAlign=bottom;fontFamily=Arial;" edge="1" parent="VDsyqYXPtuEwqBrCnzhW-1" source="MrWMUG4uQ_69N9tKeiNV-0">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-3" value="Wi-Fi" style="shape=link;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;labelPosition=center;verticalLabelPosition=top;align=center;verticalAlign=bottom;fontFamily=Arial;" parent="VDsyqYXPtuEwqBrCnzhW-1" source="MrWMUG4uQ_69N9tKeiNV-0" edge="1">
<mxGeometry x="1" width="100" relative="1" as="geometry">
<mxPoint x="390" y="385" as="sourcePoint" />
<mxPoint x="340" y="375" as="targetPoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-4" value="Bomb" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" vertex="1" parent="VDsyqYXPtuEwqBrCnzhW-1">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-4" value="Bomb" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="VDsyqYXPtuEwqBrCnzhW-1" vertex="1">
<mxGeometry x="700" y="415" width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-7" value="Wi-Fi" style="shape=link;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;labelPosition=center;verticalLabelPosition=top;align=center;verticalAlign=bottom;fontFamily=Arial;" edge="1" parent="VDsyqYXPtuEwqBrCnzhW-1" source="MrWMUG4uQ_69N9tKeiNV-4">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-7" value="Wi-Fi" style="shape=link;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;labelPosition=center;verticalLabelPosition=top;align=center;verticalAlign=bottom;fontFamily=Arial;" parent="VDsyqYXPtuEwqBrCnzhW-1" source="MrWMUG4uQ_69N9tKeiNV-4" edge="1">
<mxGeometry x="1" width="100" relative="1" as="geometry">
<mxPoint x="790" y="385" as="sourcePoint" />
<mxPoint x="740" y="375" as="targetPoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-8" value="" style="endArrow=classic;startArrow=classic;html=1;strokeWidth=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="VDsyqYXPtuEwqBrCnzhW-1" source="MrWMUG4uQ_69N9tKeiNV-9" target="MrWMUG4uQ_69N9tKeiNV-4">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-8" value="" style="endArrow=classic;startArrow=classic;html=1;strokeWidth=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="VDsyqYXPtuEwqBrCnzhW-1" source="MrWMUG4uQ_69N9tKeiNV-9" target="MrWMUG4uQ_69N9tKeiNV-4" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="850" y="455" as="sourcePoint" />
<mxPoint x="820" y="500" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-9" value="[Bomb related components]" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="VDsyqYXPtuEwqBrCnzhW-1">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-9" value="[Bomb related components]" style="whiteSpace=wrap;html=1;aspect=fixed;" parent="VDsyqYXPtuEwqBrCnzhW-1" vertex="1">
<mxGeometry x="810" y="415" width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-10" value="[Bomb related components]" style="whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="VDsyqYXPtuEwqBrCnzhW-1">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-10" value="[Bomb related components]" style="whiteSpace=wrap;html=1;aspect=fixed;" parent="VDsyqYXPtuEwqBrCnzhW-1" vertex="1">
<mxGeometry x="190" y="415" width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-11" value="" style="endArrow=classic;startArrow=classic;html=1;strokeWidth=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="VDsyqYXPtuEwqBrCnzhW-1" source="MrWMUG4uQ_69N9tKeiNV-0" target="MrWMUG4uQ_69N9tKeiNV-10">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-11" value="" style="endArrow=classic;startArrow=classic;html=1;strokeWidth=1;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="VDsyqYXPtuEwqBrCnzhW-1" source="MrWMUG4uQ_69N9tKeiNV-0" target="MrWMUG4uQ_69N9tKeiNV-10" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="660" y="465" as="sourcePoint" />
<mxPoint x="590" y="465" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-15" value="Hub" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" vertex="1" parent="VDsyqYXPtuEwqBrCnzhW-1">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-15" value="Hub" style="rounded=0;whiteSpace=wrap;html=1;fontFamily=Arial;" parent="VDsyqYXPtuEwqBrCnzhW-1" vertex="1">
<mxGeometry x="500" y="415" width="80" height="80" as="geometry" />
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-16" value="Wi-Fi" style="shape=link;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;labelPosition=center;verticalLabelPosition=top;align=center;verticalAlign=bottom;fontFamily=Arial;" edge="1" parent="VDsyqYXPtuEwqBrCnzhW-1" source="MrWMUG4uQ_69N9tKeiNV-15">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-16" value="Wi-Fi" style="shape=link;html=1;rounded=0;edgeStyle=orthogonalEdgeStyle;dashed=1;labelPosition=center;verticalLabelPosition=top;align=center;verticalAlign=bottom;fontFamily=Arial;" parent="VDsyqYXPtuEwqBrCnzhW-1" source="MrWMUG4uQ_69N9tKeiNV-15" edge="1">
<mxGeometry x="1" width="100" relative="1" as="geometry">
<mxPoint x="590" y="385" as="sourcePoint" />
<mxPoint x="540" y="375" as="targetPoint" />
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-18" value="" style="endArrow=classic;startArrow=classic;html=1;strokeWidth=1;" edge="1" parent="VDsyqYXPtuEwqBrCnzhW-1">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-18" value="" style="endArrow=classic;startArrow=classic;html=1;strokeWidth=1;" parent="VDsyqYXPtuEwqBrCnzhW-1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="350" y="395" as="sourcePoint" />
<mxPoint x="530" y="395" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-19" value="" style="endArrow=classic;startArrow=classic;html=1;strokeWidth=1;" edge="1" parent="VDsyqYXPtuEwqBrCnzhW-1">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-19" value="" style="endArrow=classic;startArrow=classic;html=1;strokeWidth=1;" parent="VDsyqYXPtuEwqBrCnzhW-1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="550" y="395" as="sourcePoint" />
<mxPoint x="730" y="395" as="targetPoint" />
</mxGeometry>
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-20" value="TCP socket connection" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="VDsyqYXPtuEwqBrCnzhW-1">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-20" value="TCP socket connection" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="VDsyqYXPtuEwqBrCnzhW-1" vertex="1">
<mxGeometry x="410" y="355" width="60" height="30" as="geometry" />
</mxCell>
- <mxCell id="MrWMUG4uQ_69N9tKeiNV-24" value="TCP socket connection" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="VDsyqYXPtuEwqBrCnzhW-1">
+ <mxCell id="MrWMUG4uQ_69N9tKeiNV-24" value="TCP socket connection" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="VDsyqYXPtuEwqBrCnzhW-1" vertex="1">
<mxGeometry x="610" y="355" width="60" height="30" as="geometry" />
</mxCell>
</root>
diff --git a/docs/handover.adoc b/docs/handover.adoc
index 7bc52b3..efeec00 100644
--- a/docs/handover.adoc
+++ b/docs/handover.adoc
@@ -1,13 +1,19 @@
:document: Handover Report
include::share/meta.adoc[]
-== A Note Before Reading
-The team of year 2023-2024 consisted of only software students, meaning no
-hardware was developed in this year. We were tasked with simplifying the
-software to the point where it would only have to be ported into the new hardware,
-which was designed in the year 2022-2023. The goal of this year is to create
-a software framework which can be used to implement new puzzles and to make the
-development process of these puzzles easier.
+== Introduction
+
+This is an (at times slightly informal) document that summarizes how the 23-24
+run of this project went. We found the previous handover documents to be
+unhelpful when determining the 'actual' state of the project in the first few
+weeks, and felt they did not address the pitfalls of this project.
+
+The team of year 2023-2024 consisted of only software students (see
+<<tab:proj-comp>>), meaning no hardware was developed in this year. The goal of
+this year is to create a software framework which can be used to implement new
+puzzles and to make the development process of these puzzles easier, and allow
+the entire software stack to be ported to the the hardware designed by the
+22-23 group.
Previous years' groups have put their predecessor's documents inside their own
project folder, which has resulted in what we called the 'Russian doll folder
@@ -19,35 +25,21 @@ require credentials to log in. Please note that this is very much unofficial,
and is not managed or endorsed by Avans. <<pn:blansch>> is the contact for
removal or transfer of these files.
-== Introduction
-
-This is an informal document that summarizes how the 23-24 run of this project
-went. We found the previous handover documents to be unhelpful when determining
-the 'actual' state of the project in the first few weeks, and felt they did not
-address the pitfalls of this project.
+== Group history
-== Group History
-
-=== 19-20
-
-.19-20 group composition
-[%autowidth]
+[[tab:proj-comp]]
+.Project group composition
+[cols="15,35,20",width=55%]
|===
-| Name | Study path
+| Year | Name | Study path
+.4+h| 19-20
| Daniël Janssen | Software
| Dion Legierse | Software
| Jop van Laanen | Hardware
| Max van den Heijkant | Software
-|===
-
-=== 20-21
-
-.20-21 group composition
-[%autowidth]
-|===
-| Name | Study path
+.4+h| 20-21
| Joost van Wiechen | Hardware
| Justin Maas | Software
| [[pn:creemers,Merel Creemers]]Merel Creemers | Hardware{empty}footnote:[The
@@ -59,40 +51,19 @@ may indicate that they were removed from the project group. I am unsure if they
were a hardware student that worked on the PCBs or a CMD student working on the
puzzle box chassis.]
| Vincent Lengowski | Hardware
-|===
-
-=== 21-22
-
-.21-22 group composition
-[%autowidth]
-|===
-| Name | Study path
+.5+h| 21-22
| Alex van Kuijk | Hardware
| Jef Baars | Software
| Julian de Bruin | Software
| Lucas van Gastel | Software
| Toon Rockx | Hardware
-|===
-
-=== 22-23
-
-.22-23 group composition
-[%autowidth]
-|===
-| Name | Study path
+.2+h| 22-23
| Frank Bekema | Hardware
| Jasper Gense | Hardware
-|===
-
-=== 23-24 (current)
-
-.23-24 group composition
-[%autowidth]
-|===
-| Name | Study path
+.4+h| 23-24
| Elwin Hammer | Software
| [[pn:faase,Lars Faase]]Lars Faase{empty}footnote:[<<pn:faase>> was removed
from the project group on 2024-06-03 following complaints about the lack of
@@ -101,98 +72,170 @@ communication, and lack of motivation] | Software
| Thomas in 't Anker | Software
|===
-== Project State
-The current project state is as follows: No new hardware has been designed
-or developed this year. The software was completely revised, now consisting of a
-a puzzle bus driver, a main controller, a simple CLI application, and two puzzle
-modules. Namely the puzzle modules 'Vault' and 'Neotrellis', both using an Arduino
-as the controller. The main controller (a RPI Pico W) can interact with the
-different puzzle modules using an I^2^C bus. The I^2^C bus has been configured to
-be a multi-master I^2^C bus, allowing the puzzle modules and the main controller
-to initiate a I^2^C transmission. The main controller is able to find
-new puzzle modules on startup, and does not check for new modules afterwards. A
-simple CLI application has been developed, which can communicate with the main
-controller through a TCP connection and simple commands.
-
-In short: A puzzle bus driver has been implemented to allow for communication
-between the main controller and the puzzle modules. A CLI application was developed
-which connects with the main controller to monitor/edit the game state. And the
-software for the puzzle modules 'Vault' and 'Neotrellis' is in the prototype state.
+== Project state
+
+The current project state is as follows:
+
+* No new hardware has been designed or developed this year
+* The software was completely revised, now consisting of
+** a puzzle bus driver (``pbdrv``)
+** a main controller
+** a simple CLI application
+** two puzzle modules ('Vault' and 'NeoTrellis') integrated using the puzzle
+ bus driver
+
+Functionality:
+
+* The main controller (a RPI Pico W) can interact with the different puzzle
+ modules using a central shared I^2^C bus (referred to as the 'puzzle bus')
+* The main controller is able to find new puzzle modules on startup, and does
+ not check for new modules afterwards.
+* A simple CLI application has been developed, which can communicate with the
+ main controller through a TCP connection and allows control over various
+ aspects of the puzzle box using simple commands.
+
+Documentation:
+
+* These project documents
+* Detailed usage and API documentation for all software modules cite:[pbdox]
== Incidents
-There were a multitude of different challenges we had to face before getting to a
-working product. The majority of these have been documented here, and it is highly
-recommended to have a look at this before development.
+
+During this year's run of the project, we encountered several difficuties we
+feel need to be addressed in order to be mitigated in future runs of the
+project. We recommend that these incidents are analyzed by future project
+groups and incorporated into the risk analysis section of future project plan
+documents.
+
+=== Documentation
+
+We spent too much time working on documentation at the start of the project.
+Make sure you set clear deadlines for documentation, and try not to spend too
+much time on review procedures, as these cost a lot of time.
+
+Our project documentation was originally written in Microsoft Word, but we
+later transferred all documentation to AsciiDoc because of issues where
+OneDrive would roll back changes. If possible, use a documentation system or
+format that allows using an external version control system like Git to avoid
+losing content. This is also the reason why our documents may contain
+formatting/style errors.
=== Misconceptions
-Make sure to know what you are developing and do some research beforehand, to make
-sure you have the complete picture about what you are using. Sounds stupid, but it
-happened for multiple project attempts, and caused time loss. This also includes
-when you want to use documentation of previous years: go through the documentation
-and verify it on the lowest possible level for the same reason as previously
-mentioned.
+
+Make sure to know what you are developing and do some research beforehand, to
+make sure you have a complete picture about what you are using. Sounds stupid,
+but it happened for multiple project attempts, and caused time loss. This also
+includes when you want to use documentation of previous years: go through the
+documentation and verify it on the lowest possible level for the same reason as
+previously mentioned.
=== I^2^C
-I^2^C is easy to implement but also easy to underestimate, this project requires a
-multi-master structure as communication is otherwise too complicated compared to
-other means of communication.
-
-For I^2^C on hardware level: make sure to use pull-up resistors as it is otherwise
-impossible to use I^2^C due to incorrect messages. This is also required for
-controllers which are connected to the I^2^C bus. Make sure to use I^2^C devices
-that support arbitration when using it as a multi-master.
-
-The RPI Pico W (RP2040) does supports multi-master to the point of being able to
-receive messages from other multi-masters as a slave while being configured as master.
-Everything else about the I^2^C bus works, but due to this limitation a workaround has
-been implemented to be able to continue using the RPI Pico W.
-To simplify; a controller is needed which supports multi-master
-while being able to be addressed as a slave.
-
-=== Available Hardware/SDKs
-When choosing or using specific chips/SDKs make sure it is available for (at least)
-a few years. This makes it easier for the next project team to use the same chips/SDKs
-instead of having to find new ones. This also includes having enough development boards
-for multiple people to program using the same setup, e.g. the RPI Pico W requires
-another RPI Pico W to be debugged. Effectively requiring the project team to have at
-least 4 RPI Pico Ws to be able to develop in the same environment (if there are 2
-software students).
-
-=== Arduino
-Allocating memory using 'realloc' on Arduino is not possible, which makes it impossible
-to use the 'mpack_writer_init_growable'.
-
-=== Garbage workarounds
-
-This section details unelegant workarounds that should be removed from the
-code. All workarounds are marked with ``FIXME:`` comments referring to one of
-the workarounds mentioned in this section.
-
-RP2040 I^2^C limitations::
-- All puzzle module drivers have a hard-coded 2 second delay between receiving
- the MAGIC handshake request and the MAGIC handshake response handler. This
- was done to ensure responses are not ignored by the RP2040 (main controller)
- while it is still in I^2^C master mode.
+
+I^2^C is used because it is widely available and easy to implement. We strongly
+recommend 3rd year software students to refresh their knowledge on I^2^C before
+making major design decisions that rely on their conception of how to I^2^C bus
+works.
+
+Please note the following differences between I^2^C devices:
+
+- Regular I^2^C slave peripherals are allowed on the puzzle bus, and can be
+ connected to the puzzle bus as long as they do not cause issues with
+ addressing.
+- I^2^C master controllers must have hardware support for a multi-master
+ hardware configuration (i.e. support bus arbitration on a hardware level).
+ Arbitration support is required to prevent message corruption or electrical
+ shorts in a multi-master setup. Multi-master controllers may also be
+ connected to the puzzle bus, but only as long as they only interact with
+ regular I^2^C slave devices.
+- I^2^C multi-master controllers that are slave-addressable in master mode are
+ the only kind of I^2^C controller suitable for use in puzzle modules.
+ Microcontrollers with 2 I^2^C peripherals on the same bus (one in master
+ mode, one in slave mode) can also be used to achieve the same effect.
+
+The RP2040 supports multi-master, but is not addressable as a slave in master
+mode. This was mitigated using a workaround (see <<fixme:rp2040-i2c>>).
+
+=== Development hardware availability
+
+When choosing or using specific chips or development boards, make sure to
+include research on the product lifecycle. Choosing boards/chips that have
+planned long term support makes it easier for the next project team to order
+and use the same chips/boards instead of having to find new ones.
+
+Due to a lack of foresight, only 2 Picos were ordered this year, which caused
+unoptimal workload spread during the last weeks of the project. Because of
+this, we also strongly recommend making enough development boards available for
+multiple people to develop using the same setup. Note that the RPI Pico is a
+special case, as it requires another Pico for debugging, effectively requiring
+double the amount of hardware to support developers.
+
+Due to a misunderstanding, we also thought our development boards went missing
+somewhere during week 13. Double-checking if project materials were actually
+stolen, or making clear where the materials are stored by sending an image of
+its location could have easily avoided this from happening; make sure to do
+either.
+
+=== Auxiliary workarounds and technical limitations
+
+This section details workarounds that were implemented instead of being fixed
+due to time constraints or project scope. Workarounds that should be removed
+are marked with ``FIXME:`` comments referring to one of the workarounds
+mentioned in this section.
+
+[[fixme:rp2040-i2c,RP2040 I^2^C limitations]]
+<<fixme:rp2040-i2c>>::
+- The RP2040 is not slave-addressable while in master mode. A workaround that
+ uses both I^2^C peripherals simultaniously was written to work around this
+ issue.
+
+Memory management on Arduino::
+The Arduino's built-in memory management functions do not seem to work
+properly. The FreeRTOS heap 4 memory management functions are used on the
+puzzle modules instead. FreeRTOS does not have an implementation of the
+``realloc()`` function.
+- mpack's writer API cannot be used with a writer initialized using the
+ ``mpack_writer_init_growable`` function on Arduino-based puzzle modules. The
+ ``mpack_writer_init`` function is used with a static size buffer instead.
== Recommendations
+This section details our recommendations on course of action for future project
+groups.
+
=== Imperatives
-* The 22-23 design document already mentions that the application of the I^2^C
-bus is in a multi-master configuration, but does not mention that this only
-works when pull-up resistors are used on the SCL and SDA lines. The pull-up
-resistors are required, as omitting them makes the bus arbitration process
-very inconsistent which causes frames to be dropped entirely.
-* Start creating prototypes as fast as possible; this benefits the project in the long run,
-as you have already shown that certain parts of the project are already working and "only"
-need to be integrated.
-* The Atmega328P chip is sufficient for the puzzle modules as it has enough I/O, mutli-master
-hardware support, and the ability to be addressed as a slave while being in master mode.
-* The hardware design can be taken from the year 22-23, and the game rules are taken from
-the year 20-21.
-
-// TODO: rename this bitch
-=== Loose imperatives
-* The RPI Pico W has programmable IO modules, making it possible to create an I^2^C driver
-that allows multi-master communication while still being addressable as a slave.
+
+The following points must not be dismissed by future project groups, as they
+are critical for project success:
+
+- The 22-23 design document already mentions that the application of the I^2^C
+ bus is in a multi-master configuration, but does not mention that this only
+ works when pull-up resistors are used on the SCL and SDA lines. The pull-up
+ resistors are required, as omitting them makes the bus arbitration process
+ very inconsistent which causes frames to be dropped entirely.
+- Start creating prototypes as early as possible; this benefits the project in
+ the long run, as you have already shown that certain parts of the project are
+ already working and "only" need to be integrated.
+- The Atmega328P and ATmega2560 MCUs are both sufficient for the puzzle modules
+ as they have enough I/O, mutli-master hardware support, and the ability to be
+ addressed as a slave while being in master mode.
+- The RPI Pico (and Pico W)'s I^2^C peripheral supports multi-master, but does
+ not support being addressed as a slave while in master mode. This is required
+ for puzzle bus integration, and was mitigated using a workaround (see
+ <<fixme:rp2040-i2c>>).
+
+=== Other suggestions
+
+These points are suggestions for future project groups. While we do not think
+these are critical to project success, we still think they are important to
+mention.
+
+- The hardware design from the year 22-23 should be implemented.
+- The original game rules are described in a separate document from the year
+ 20-21.
+- The RPI Pico W has programmable I/O modules. Due to time constraints, we did
+ not research if these modules can be used to create a custom I^2^C peripheral
+ (and driver) that allows multi-master communication while still being
+ addressable as a slave. If this is possible, the RPI Pico W could be used
+ without the use of workarounds.
include::share/footer.adoc[]
diff --git a/docs/img/.gitignore b/docs/img/.gitignore
new file mode 100644
index 0000000..529fbaa
--- /dev/null
+++ b/docs/img/.gitignore
@@ -0,0 +1,3 @@
+software-components.svg
+sequence-puzzle-module-init.svg
+sequence-puzzle-finish.svg
diff --git a/docs/img/main-controller-state.svg b/docs/img/main-controller-state.svg
index 6e0333b..f82a8c0 100644
--- a/docs/img/main-controller-state.svg
+++ b/docs/img/main-controller-state.svg
@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="221px" height="61px" viewBox="-0.5 -0.5 221 61"><defs/><g><path d="M 54 48 Q 70 60 80.91 51.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 85.11 48.67 L 81.61 55.67 L 80.91 51.82 L 77.41 50.07 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="30" cy="30" rx="30" ry="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 30px; margin-left: 1px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Reset</div></div></div></foreignObject><image x="1" y="23.5" width="58" height="17" xlink:href="data:image/png;base64,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"/></switch></g><ellipse cx="110" cy="30" rx="30" ry="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 30px; margin-left: 81px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Playing</div></div></div></foreignObject><image x="81" y="23.5" width="58" height="17" xlink:href="data:image/png;base64,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"/></switch></g><ellipse cx="190" cy="30" rx="30" ry="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 30px; margin-left: 161px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Solved</div></div></div></foreignObject><image x="161" y="23.5" width="58" height="17" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOgAAABECAYAAACLd3ntAAAAAXNSR0IArs4c6QAADOtJREFUeF7tnQWsNT0Rht8fl+AOCRLcIWhwd3d3d3f3ENw1uLu7S3ANLgkePEBw3SdpyWTS3W1399z/7LfThADfabvTad+Z6UjvYYoWHAgO7C0HDttbyoKw4EBwQAHQOATBgT3mQAB0jzcnSAsOBEDjDAQH9pgDAdA93pwgLTgQAI0zEBzYYw4EQPd4c4K04EAANM5AcGCPOXAoAvTYki4o6RLpv88p6fhpD/4k6SuSfiDpk+k//O9/7fEePVTSowx9D5P06D2mdx9IO6Ok10li72nvk3RjSb/dB+JaaDiUAHpqSfeWdHNJx2pgwte7/k+W9EZJf24Yd1BdA6DtnA6AtvNsZyOOKuk2SctkTTnlY5+SdA9JX5T03ykT7GhMALSdsQHQdp7tZMTRJd2vm/kRC83+I0m3kvSRPQJpALR9cwOg7TxbfATm+Q0lPc+ZtNwz3yLpVZK+Kun3kv6Rvs4Y7qink3QlSbeWdCpHGWOY91uLUzxtwgBoO98CoO08W3wEd85XSrqwmfmznSPgrpK+UKkBuas+SNIDHHXPl3RPSX9dnOr2CQOg7TwLgLbzbPERaL8XmVnReDeQ9LXGL3GHfbikB5pxv+i8vdfotOznGufaRfcAaDtXA6DtPFt0xNGS5/VOZlY8uE+t1JyemJI2BhiPnTjfkosNgLZzMwDazrNFR5wg3TEvb2a9XGfufmDiV46YtChgyA3tfPfOCfWXiXMuNSwA2s7JAGg7zxYdUQLoxSV9fMZXrtY5jF6SHEv/7ALb30v30z9WznkESRyMq3Z0XErS+UyCxJfTvO+W9MHkuKqcVmMAPaukN3SB+TOnCaH7OhNM/ZMnoUeCBw0zn7UQdhpqeNIv0K3vmpLOn5JD6P87SZ+XRPgKp903Jf2ndtGFfvY7F5V07tTnY9134etrOw/8j9O/BUBnMHqJoceT9IruAFzZTDbHxJ1DE8BEONxfktXofXNycPE8P03Srys+PAbQY0p6lqRbmLnuIAlHV0u7rKT3mwEvlXSXgeQN7u7X7kBHZhOAGGvvTFYKwqolzgx/EXiPS0JviK/QguXDlSUyicZ2ZIe/Y5KS7mYdO3hwb3nA4RGkOoKBWGxL9hKsQbPcTdKXRvg0BlCGX0vSm8w8CK87d7QRcqppR5H0hOS5zv1J/nhxz+CTSnpilzJ505rJTR/owWuOgKpJr5zCX+ZHGMCDSPVr3KAlu186mU4WGJhUD06JBjUHYA49aC4OqXVU5fm+I+lDyeTi8F8ohYM8iOl3uxHTvAagp+m02GuSqQkNteZpppdY8KsTnfwbseDrd/Fg6PPtJEk7X939APjwen8mCQbWepFkXfg5CGuRXjm0R0dKwg/B4RvCmKsC3zylJM6C1eJP6QQgFsHZ08DIxZ1z0ieOBSB4bW9bGE9+LTFSJOl3K6V1Cxlo8HslgNpxaEUkOIn4/r51onTgALQFKocNTcTdsdRqAFrSgNAHf2oa9++3mY7PSFbB393gklACJM+R9PQkGOwQEkMQHo9JyR/5N8YgmLg39jWcfuRHW17BXywWBLHlL2DGDEZgZq1p5w2A1pyCHfRBamKG2WQF/xnufGgz/oMTieqVnFk0laTzpsNjs5AwqTg8Q/dKDizOFCS8HYs2QfN7QEBfDUDp5y0KDjdm6h9GFsldkoONuZ0bd8s3F8ZREYLgs0BD4KB9hxxApZRM0ikRTD8rfAcfA3fo65rfECCY7aX+uRuOMhx9OK0CoFNP98LjOOhoCg5+TUN6I4mRqjhFWjVsKSQzdNg8TYAU4LzA/EAOMJ5XMqB8qwXoySS9vNPel0kT1Jq53jz+aCrN+rkjBNAgDC2fa0zVPA0pls+UdDMzb9891wubliQUNClCBH7kFhq0Bhk77IMWwFGC0yjfO2o/Bzg4eC8zbvqhsf6+Rt8+jdM3T+mw9yVG1AIU4KOFba1ojZnrHUyMf2Snuf/tiPegaRFKeaoaLV9yAPbRVOJvySIIgNaiYcf9cqwMKY0To6X8LN+lMPcwi/uaD0f0aZyxpd4+eTNzvz6TtBagzEMc8q1GexB/JCWSgoFSg19YH9BCgwdoSK4DtpXAPyXTysdaSzHbEyYP7BUMAa1JKH6PAqBjp/Fw+B3HyRmSyUd8kntqTSgE85cD+40emtHSxORy44Bj6rXea88j6R0GTH2e0xaAHifFATGXaWM5xT6g/950L/yNWzt8e7YLq5D3TKyxpR0jOZMwbXNDkL7d/P9zpPv96dO/fbq7htyoC6Fh6dQ2qpVwQMFjWgC0lnOHYz8Ae9r0FApeyyHA9sVU53pL7fK9NuE3whIICNtaAMo4r5mHEji806evb4lWkiN+2rifR+7CMGhG69TzSRUXk0R2UG7vSoKhzwookeATWQKgjRu1D90JGXAY8EJepUDQC1Pg3j6D4k1Cht0kpci1rqmUrrgEQH3qX5+Z6zOQhpxKXtO2rnWov39jyQuNKaV/fp8CoEvu2AHPRSrZFVPg3Aa7S/exXQO0BPZWDepp7DNzPZCHso8CoAd8KPPnDqVHw+aykHxaPLk2Pvn4FIfMHs1dA7TkDGkFKHzwntmS6erraYdS+wKgc0/XxPFrBCjOAx73whEAYCgHI+Bdk3g+xKZSfNN7VncN0CVMXNboY5ve+eOdPsQZSQroc4x5gA6lAk48iv8fFiau4eAaAeq9n1PLq0oHyae8+bvLkk4iH0/FpEaDkss6x0nEWB9LZG7M+OyA8p7SvtS+TIf3ivbROhecjMeBRKpkblPuj14ATZljibXMnmONAC0lCkx11HgGeg9iaWN5q4hUvdzIQ8WE/FvjbvC4NplMOfRD3SWhi+8vAFCm8EkBNm7p1zCWaFEq71uK555tZ5L0epNwMkVbe69zALTxcM7pXqp/pGCZ8EKLK75Egw9RlF5V2OdEBbsmn/qXzVyK0VlXjpXWxBlLlsOY1i3xN+fYkoyAWY0wIhZshVJJGPhY6dj5QQu/xwi/AOgYxxb+3Ts4mJ57KE9tthQDW7JKCdqlVLklNPiJJRHGwaTObW6qn2cx1hGakkR8Wg6jAFDu1jkRwDvC+rbKO55a8mPznL5CpRTaKWUttYRaSr6EAOjCAByb7hQpHeySpiOZJvdNhcutT2uUag/7HCe7SJYfyviZ4sXNbPGpfyQF0CiYpvWl9pX4X3pYDfOeYvWaP5lBuR1As8n2ZCJRduaflfF0Qyca37740HdGuF+TRZSfgKFfAHQMUTv4nfsaFSE2fY+N5BBQNZHfpxn7NAeHQ3Yf15F0Pp7jLBUVl8rNMLN5k/eXAx/sKzcjKwcaSu/wzgGoT/2DRiyM6yUa+1L7SkuAdkrSeKrFNl71J3956A1hEtixRmyKJHuF1WPrUPO89OdFRe72uZHdRbnZ0BtJCG5SEn0xeQB0DAU7+J1N5HD4R6ezZqBYG0nKkyK/MrmyaMvjdmbe2ZJU5hV5n1TPoeE+2ge2voJtCokp2P5woT6SzCEOOGanL9geeqplDkDhRek6kLej9R2nkhZkLl5zoOLk24UrBpqX6hhbZsaYMe1bqu3khQf+0hvPu9jaWZJNeKQNc75UGxwA3QEAa6bEYYSk5XnMpRqhCA516bkP+40lnjzBLOevsdncU7+OuQD1GUN5/rFE+j5+9hVF058HwXiKhD/zh2OJ5A+8yb5hqt6xA+0PRzatlDzCEPukDIKPGtj8yl9pygDoUuiYMA+alGqHJzWWl5U+RcHzQzqA/qSSDkCKBkdA1FTK2GnRtmhUH/dcGqCl5Aq+UfviQokVOJgwy3H6tDbAyWuBfU+82Pkwq0muf27hb+j0fRfTmQoj3irKLx0GQFt3aQf9CStgKuJ08H8QaexzmMPENtFkrQ6m/CwkSd+81zrWqDXlISzuz2PPkTDXXA3KHN4Dy78NpfaNrYHfEU7wGuFUw2/WzdtErLvGqWRp6DOTPZ1oVgQsIRbM3VznGgCt2dED6oNpxasKvEvDvYQSs3M5DYfW4r7ES/SfSGVTU8MzeVncbTGzcjmVfbia73EX5oFlvlf7GPZSAPWhobHUvpatAqjc+3DMwHfL68xntHXruj0NCMKzpNcGMX3zd7gm4ECiagf+wtuoZmnZwegbHAgOTOPAGlP9pq00RgUHVsiBAOgKNy1I3g4HAqDb2etY6Qo5EABd4aYFydvhQAB0O3sdK10hBwKgK9y0IHk7HAiAbmevY6Ur5EAAdIWbFiRvhwMB0O3sdax0hRwIgK5w04Lk7XAgALqdvY6VrpADAdAVblqQvB0OBEC3s9ex0hVyIAC6wk0LkrfDgQDodvY6VrpCDgRAV7hpQfJ2OBAA3c5ex0pXyIEA6Ao3LUjeDgcCoNvZ61jpCjkQAF3hpgXJ2+FAAHQ7ex0rXSEHAqAr3LQgeTscCIBuZ69jpSvkwP8ADdkycl/zhb4AAAAASUVORK5CYII="/></switch></g><path d="M 86 12 Q 70 0 59.09 8.18" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 54.89 11.33 L 58.39 4.33 L 59.09 8.18 L 62.59 9.93 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 134 48 Q 150 60 160.91 51.82" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 165.11 48.67 L 161.61 55.67 L 160.91 51.82 L 157.41 50.07 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 166 12 Q 150 0 139.09 8.18" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 134.89 11.33 L 138.39 4.33 L 139.09 8.18 L 142.59 9.93 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="281px" height="81px" viewBox="-0.5 -0.5 281 81"><defs/><g><g><path d="M 74.3 60.58 Q 90 70 100.24 63.86" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 104.74 61.16 L 100.54 67.76 L 100.24 63.86 L 96.94 61.76 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 1px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">idle</div></div></div></foreignObject><image x="1" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><ellipse cx="140" cy="40" rx="40" ry="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 101px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">playing</div></div></div></foreignObject><image x="101" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><ellipse cx="240" cy="40" rx="40" ry="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 201px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">solved</div></div></div></foreignObject><image x="201" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATgAAABECAYAAAAV6ClkAAAAAXNSR0IArs4c6QAADppJREFUeF7tnQOwNEkWhc+sbWvWtm3bdqxte2dtI9a27Vjbtm17t76JyogbN6q7szJfTf/x3rkRE/+87ryZWae6Tl9m7yeLETACRmCXIrDfLr0uX5YRMAJGQCY4fwiMgBHYtQiY4HbtrfWFGQEjYILzZ8AIGIFdi4AJbtfeWl+YETACJjh/BoyAEdi1CJjgdu2t9YUZASNggvNnwAgYgV2LgAlu197axS7sAEn3DbO/VdLlF1tt90z8v3Qp55H08d1zefvmlZjg9s37si/vygTXdndMcG24dWmZ4Lrg25PKJri2226Ca8OtS8sE1wXfnlQ2wbXddhNcG25dWia4Lvj2pLIJru22m+DacOvSMsF1wbcnlU1wbbfdBNeGW5eWCa4Lvj2pbIJru+0muDbcurRMcF3w7UllE1zbbTfBteHWpWWC64JvTyqb4NpuuwmuDbcuLRNcF3zNyqeXdHVJZ5d0GklHlXRESf+W9CdJ35f0FUnvkvRmSX9uWOlgki4m6RKSLiDpOJKOIemQkn4r6TeSPifp/cM+3iLpV5VrbCK4l0u6dpjrq5JOVzl3HvZ5SWcKL74yzT017UkkXWG87lNIOuaILdf8a0lflPTO8ZrBoEXA8CrDXFeVdJYR28NK+r2kb0p6n6QXSPpumNwE14J0p44JrhPAmeqnHcjsSZIuPkOPB/MRw0P6OEn5IVk1zZUHInuYJNarkb8M5PdUSQ+X9McNCpsIjq4GSDkKBAfRzZFTSvpGUmBuOiem5HiSHjJ8OdxY0sErFuKL5DGSHivpbxXjy5BzSnpeBWn/R9LjJd1bEv9vgpsB8k4NNcHtFJKb57ngaDVgqbXI60er779rlLmfj5J095YFJH1J0mUk/WSN/iaCw7r5maSjhzkeOJLPnG3dP+lgYUJiWLlZzirpbZKOPWeBcSztUpeV9LsK3fNKes+AMdZarbxmIPdrDu1t/0rE61atWgQ7xpngOsCboXoUSV8bXZmixoP6xvGB+fbomkIOuJJnGx+Kk6Y1Hjz8/aA162Ll3SW9j6Xy0tHd/dForRxL0rkkXU8S7nIU9oJb+NcV62wiONSeIelWQf/Lks4wAy+GohNd2ycPJHTHiTmY96ODJXaE9N7bBwv2VSPuYHC0MSTANRMaiIKrfm5J/1yzR9x7LErmifIBSS8cLVQsYbCFCG8g6VTjwLuNFvWhg6IJbuYHomW4Ca4Ftfk6WFSPDmrEgnBTv7BmKtwsXK77hDE8QPuP8bOseuEx9hPv6YfHmNUqi4w1sJSwsKLgrt6+g+DOP8T/PpT0Tz3hcq66fIgNgotyjqGp/9PptUNJ+pSkM4bXcbGxmIizrRLI9ymSDhEGbPryAJPbpgn5MnnCikX4ssLlh9yIoR4mrWeCm/8czdYwwc2GrEmBoPNFgibkwQNTI68dg9llLDEmLIYsnx0D3uX1bw3xKkjhDxWLPEvSLcI4YkYQ6RQx1lhwfK6+N85RpoVI0a0RiJ3xRbB+p+KJdx7jXGUc+4boIfZNAjlh8RbBeuOafz6hiAX+yzFBU94miXCTTYtIerGk60+MM8FVgNc7xATXi2CdPm7fycJQLJyP1KkeSFK4O2RW+e8zw4P1g6SLy4UlE+Uag/tJ/KdGcKuYO8aWOBIJCyRLDcGhQ2LkXkEZa/XMNZsZLT2SDEWwYpkvCp9dMpYnDy+ucmOnlkUf4ixuJGPuMSYe8vgbpi8VEgZkaL9TcT3EDRmHBRfFBFcBXu8QE1wvgnX6X08P0nUkvaJOtWoU2TqsmSJkXiEtLJpaecNQNnKlMBiLkFhgllqCI7ZH0iIKpIVluU4gQWJiRSCTE0v6YVKi9OWD6TVKRCDqWrlTcjHZb3R3yzyUp+D2FqF8hfKQWsnYomeCq0WvY5wJrgO8GaqUNpCpK0Is6Xwbgtozpj/QGiSwXYRatOvOmWBwwW4z1Iw9LejgspHxzYH3WoJjKmrOYnJhyhLL28yWH0H86N6X8fccrKJHBuWWejtqEGP5CmR6pIm6Q8YwtsgcSxGdWw7Jo2emCzXBzfyAtgw3wbWgNl+HwldIJwouGy4gRbarMpY1K5EoILB+uDCY2qv48NfMA4kQK4yClYK1EmUOwWUSwjKjpGOd4M7F7PFNh9jY8ycUXjcW25a3yBRPxbrWrcXnH+yj+5jDByQLSO7wb5E5MVR0pqxNE1zNp7JzjAmuE8BKdUgIK+5SE+P/Mcbj6CiAYD4x07Wk9isHxufE38qWTjQR26MjAAJuJTjmxGWMnzNiZqtiV8QbPxkWowCXspmp4mPIMsb0Xj245U+vvB9xGEmAE4QXbj78/ZzwN+9RXhPlihPFzOuWPr6kH6cBJriGmzVXxQQ3F7H28dRpvShZHVOzUXD6jpFYIJdNnQVTFf+UoLx35lbJFOZiV2rGXtZBcKgSJ8OCKULigWLkKaGr4K7hDeKUxCunhCwtsbmdFkp62EeR7MbyOtYurnOt4PbmbLYJrha9jnEmuA7wGlWJjVECQV3YJsG6wxXjgSPoPyXZ6mFMy8ODC5bjbcTlKNqNMsdFRY+aszgH8Uf2nIXPItnhE4Y3Ljd2KExdN4kUenh3Wh4q6QFh0il8KQrG0q4VLPjcgdFyj2rX87gRARPc9j4KPDg0a9NfmbsJ8q4IfkNyxLRyT+NUiQgJh4/NvDSKZiHUKJATNXI9BEflPy50jGFNZTvZcyyd+cXoOk61ZrEf6tJopN9poXA3doPQ8ZF//WouOVF+k+Osc+fY6evcE/OZ4PaN20yMhlM/iNFxAsiqB5dM3K3TlqnHoh4sCnPRMzlHsIawiqJMlbPMteCY703jCR9l7uwG8jqHENwhLP7EVPqSr4Vyk1gD19LvWoPPVLnLRcdTWGr0GUObVz6txQRXi17HOBNcB3gLqXLMEVbDzYbjdigwje1ELHnp1IZEvRvWTpRrjX2Yc7aIVRWP90GX0hZ6OqO0EFzOIuPe4eYV4ZoJwh83vEYN3iq3nGEUNseeUmoBY/xuzrWvG0ucj3hfFOoFIe1amYrjmeBq0esYZ4LrAO8gUOUBJuEQT+agaJSzyIpwDzmHjEB2kTltUUXnkhP9m7RHUe0fpYXgKGGBhGNDPG1RpXj3QiloX1PTRvIjJiCIVV5tgXvC3ukljc8Klia9rLXC8VWcBhPFBFeLXsc4E1wHeAeRKnVgzw1rcRQR7T9RKDGhB7MI/ascqDlHsH5i9pATOMis5uOZWgiOfZBBpuWsCCeDUDCL5Eb2mjq+3IdKgmKJrCr7o9QFQi6y7jCCKcxzby1jTHBzPp2NY01wjcA1qh1+LBqdo57r02i/ym4rBcOQQhFKS4j7cAZZrVBWQmypCH9PHczZSnC41tHd5bQPXkOoMyu1aBAqZJLrxvJ1TAX/N7m1tVjkcbkTZVVL16r56R/OBc4muNa7MUPPBDcDrMahHLEDcdAVgOVFQmHOUdm5zg1dyCvKVIznRqPVVLNtDgKgXzYS56oOglaCo1Tip2OPLHv6+3i2GuUyMdZGsTOJlhrBfY7lNi9JVuKmOcjwUs9G9pbj4Vl76vSV3LNKJhv3Hcw2Sc4Ol/EmuE3I7cD7JrgdAHHDFBxvHY/Voe0I8qiVfJYchbPErLLkglpcNqyGnBnNenwGiA/FRntiepDx1FHerQTHusStbhc2gAXHgx7PowMrjiKqEWJhZF+j1HYZkNigiT668qtceyzK3MTPSS10jKwTykO4L/mATXRMcDV3uHOMCa4TwAr1KVcK0iPmBZGsE2rkeAhjnykW4VRLEmRGdjJaYZx0y0OI5TQlzEs5Bu1JUWgOf/YKnR6CI3Ma6/OoOSN2WE7moFaM1izifzVC7R6tXfGHabAMyUDTm7pKSNpQ3xeTEtTbUZuYe2/LHHwJkCyIwiGmHCs1VavHFwRETckOJSL0u8bj6k1wNXe4c4wJrhPASnU+6LiMUcjMcWQ5DzxlCPxNMSxuE24Xv43AQxCFBn0ewlWxtfsN5/5TiR8FEuWATGJeHGDJPYdEsAJpTo+dA+jlLG2+xB6CY654Nh7EGxMmZEZpD5sj1KmBYT6ynDISjiwnXoZbD8FQCsNvY1BGk38bY9X5d2UvhAqYC1KNwjHmHKTAv5ArvcG0pmERlz3xBYKVGnteOU2GLyDLggiY4BYEN0zNw8UvTc35Na28M+JNuHT5XLQ8jjYjjt9uEawe3Od1v03QS3AQMEQ8JZA6ZTFzBeuVRADE3SKcvBKTNKvmwBqmPxb3tlbKKSe5MJkvmHyeXe2cHleJgAmuEqgdGEaQnfP5ianFurZNU2MVELuCWDY13pe5IAoa2mt/6IX4EqUMU8cS5f31EhzWaa6tYw3q5EjAzDmkM+6NImF+kAeCzlnmVRhjkXGK7xxSJWxAiCBbvnkNssEciV5+NjBnUqk7fPemm+/3+xAwwfXh16JNqQgtWVhzuFecfXbkMc5GLyjxJ8omePjI8OEy1vyuQt4LVgbZW6w+XCYIoGRfcdkgFFwkHjIe8NqSkl6CY59TZRO5B7QFW3Qoq4GEiH1BplwzbWhgy2kpWFK4r1h8WFC1vzUb94PriTWHG8o9xC3FSi8//ExdIl8W8VgosrTsqQjxP4qTLQsiYIJbEFxPbQSMwHYRMMFtF3+vbgSMwIIImOAWBNdTGwEjsF0ETHDbxd+rGwEjsCACJrgFwfXURsAIbBcBE9x28ffqRsAILIiACW5BcD21ETAC20XABLdd/L26ETACCyJgglsQXE9tBIzAdhEwwW0Xf69uBIzAggiY4BYE11MbASOwXQRMcNvF36sbASOwIAImuAXB9dRGwAhsFwET3Hbx9+pGwAgsiIAJbkFwPbURMALbRcAEt138vboRMAILImCCWxBcT20EjMB2ETDBbRd/r24EjMCCCJjgFgTXUxsBI7BdBExw28XfqxsBI7AgAia4BcH11EbACGwXARPcdvH36kbACCyIgAluQXA9tREwAttFwAS3Xfy9uhEwAgsi8H8AEIljoW6tTwAAAABJRU5ErkJggg=="/></switch></g></g><g><path d="M 105.7 19.42 Q 90 10 79.76 16.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 75.26 18.84 L 79.46 12.24 L 79.76 16.14 L 83.06 18.24 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><path d="M 174.3 60.58 Q 190 70 200.24 63.86" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 204.74 61.16 L 200.54 67.76 L 200.24 63.86 L 196.94 61.76 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><path d="M 205.7 19.42 Q 190 10 179.76 16.14" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 175.26 18.84 L 179.46 12.24 L 179.76 16.14 L 183.06 18.24 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g></g></svg> \ No newline at end of file
diff --git a/docs/img/main-controller-top.svg b/docs/img/main-controller-top.svg
index 5bb7cda..601b402 100644
--- a/docs/img/main-controller-top.svg
+++ b/docs/img/main-controller-top.svg
@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="149px" height="188px" viewBox="-0.5 -0.5 149 188"><defs/><g><rect x="67" y="55" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 95px; margin-left: 68px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Main controller</div></div></div></foreignObject><image x="68" y="81" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 107 166.63 L 107 141.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 107 171.88 L 103.5 164.88 L 107 166.63 L 110.5 164.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 107 136.12 L 110.5 143.12 L 107 141.37 L 103.5 143.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 67 175 L 147 175" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 175px; margin-left: 59px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Puzzle bus</div></div></div></foreignObject><image x="0" y="168.5" width="59" height="17" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 105 55 L 105 35.52 L 105 15 M 109 15 L 109 35.52 L 109 55 M 109 15" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 12px; margin-left: 107px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Wi-Fi</div></div></div></foreignObject><image x="94" y="-0.5" width="26" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="147px" height="169px" viewBox="-0.5 -0.5 147 169"><defs/><g><g><rect x="65" y="36" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 76px; margin-left: 66px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">main controller</div></div></div></foreignObject><image x="66" y="62" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 105 147.63 L 105 122.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 105 152.88 L 101.5 145.88 L 105 147.63 L 108.5 145.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 105 117.12 L 108.5 124.12 L 105 122.37 L 101.5 124.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><path d="M 65 156 L 145 156" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 156px; margin-left: 57px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">puzzle bus</div></div></div></foreignObject><image x="0" y="149.5" width="57" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 103 36 L 103 26 L 103 16 M 107 16 L 107 26 L 107 36 M 107 16" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" stroke-dasharray="3 3" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 13px; margin-left: 105px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Wi-Fi</div></div></div></foreignObject><image x="92" y="0.5" width="26" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g></g></g></svg> \ No newline at end of file
diff --git a/docs/img/power-supply-top.svg b/docs/img/power-supply-top.svg
index 89107a6..1ba4c14 100644
--- a/docs/img/power-supply-top.svg
+++ b/docs/img/power-supply-top.svg
@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="170px" height="133px" viewBox="-0.5 -0.5 170 133"><defs/><g><rect x="88" y="0" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 89px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Power supply</div></div></div></foreignObject><image x="89" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 128 111.63 L 128 80" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 128 116.88 L 124.5 109.88 L 128 111.63 L 131.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 88 120 L 168 120" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 120px; margin-left: 80px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Puzzle bus</div></div></div></foreignObject><image x="21" y="113.5" width="59" height="17" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 48 40 L 81.63 40.17" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 86.88 40.19 L 79.86 43.66 L 81.63 40.17 L 79.9 36.66 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 40px; margin-left: 40px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Charger</div></div></div></foreignObject><image x="0" y="34" width="40" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="167px" height="133px" viewBox="-0.5 -0.5 167 133"><defs/><g><g><rect x="85" y="0" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 86px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">power supply</div></div></div></foreignObject><image x="86" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 125 111.63 L 125 80" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 125 116.88 L 121.5 109.88 L 125 111.63 L 128.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><path d="M 85 120 L 165 120" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 120px; margin-left: 77px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">puzzle bus</div></div></div></foreignObject><image x="20" y="113.5" width="57" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 45 40 L 65 40 L 78.63 40" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 83.88 40 L 76.88 43.5 L 78.63 40 L 76.88 36.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 40px; margin-left: 37px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">charger</div></div></div></foreignObject><image x="0" y="34" width="37" height="15.75" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJQAAAA/CAYAAAAG5+H5AAAAAXNSR0IArs4c6QAADn1JREFUeF7tnAmwllMYx5+UVkUppJRBixhbhJQ2Sw3tIUlIlKUiKtnaNwrtommnsk070WKpyNImLdooFaIsRVpkfmfmvHO+977r5733NrfzzNy5c7/vvOc85zn/8+zvzXX06NGjYslKICEJ5LKASkiSdholAQsoC4REJWABlag47WQWUBYDiUrAAipRcdrJLKAsBhKVgAVUouK0k2UJoE466STZv3+/kvapp54qv/zyi5V8DpWABVQOPdjs2pYFVHZJPoeuawGVQw82u7ZlAZVdks+h61pA5dCDza5tWUBll+Rz6LoWUDn0YLNrW4GAWrt2rbz11lvywQcfyPfffy+7d++W3Llzy2mnnSaVK1eW+vXry2233Sb58uUL5N/MQ51++uny448/OuMXLlwoEyZMkM8++0x++OEHOXTokBQtWlTOP/98ueGGG6Rdu3ZSrFixWPKBV/j++OOPhT3AN3mw/PnzyymnnCKVKlWSa665Ru666y4pW7Zs6Ny//fab4klT27Zt5eWXX1Z/zps3TwYNGiTLly+XvXv3Kl798mz//vuvvP322/LOO+/IV199peRw8OBBOeOMM+TKK6+UVq1ayU033eSsc//998urr77q/L1z504pWbJkKL8//fSTWgfe1q1bp/b/119/SfHixQX5V6tWTa2DfHPlyhU63yOPPCJDhgxxxu3atUvx/Pvvv0vv3r1lxowZsn37dvnnn3+821f27NkjnTt3lvHjxwtCCKJSpUop4d58882+w0xAnXXWWbJt2zb5448/lABhJohOPvlkmTp1qtStWzd04/v27ZPHHntMxo4dK4cPHw4df8IJJ8hDDz0kzz33nAKbHx04cEAKFCjgfA3fXIKJEycqUJrkl7gF2Iz98ssvA/mqV6+e2m+RIkWkadOmCnya/vzzT0GWfsSB9unTR1588UUnkRy0GEph6NChUrVq1UCennjiCRk4cKAzZsuWLQqc1atXl1WrVqU8m0FDgb7rr79evvnmm9AD0QNAOQhu37695zMmoMqXL6+YqFWrltJKUShv3rzyxRdfyEUXXeQ7HGFfe+21snLlSs8x8OjXnMp+58yZIyeeeKLv/IBPP3/LLbfI8OHD5ZxzzslwcF6A2rhxoxI+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"/></switch></g></g></g></svg> \ No newline at end of file
diff --git a/docs/img/puzzle-module-common-state.svg b/docs/img/puzzle-module-common-state.svg
index b5688ef..4b1e1fd 100644
--- a/docs/img/puzzle-module-common-state.svg
+++ b/docs/img/puzzle-module-common-state.svg
@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="161px" height="221px" viewBox="-0.5 -0.5 161 221"><defs/><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 1px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Uninitialized</div></div></div></foreignObject><image x="1" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 130 60 L 130 73.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 130 78.88 L 126.5 71.88 L 130 73.63 L 133.5 71.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="130" cy="30" rx="30" ry="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 30px; margin-left: 101px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Reset</div></div></div></foreignObject><image x="101" y="23.5" width="58" height="17" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 130 140 L 130 160 L 130 140 L 130 153.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 130 158.88 L 126.5 151.88 L 130 153.63 L 133.5 151.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><ellipse cx="130" cy="110" rx="30" ry="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 110px; margin-left: 101px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Playing</div></div></div></foreignObject><image x="101" y="103.5" width="58" height="17" xlink:href="data:image/png;base64,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"/></switch></g><ellipse cx="130" cy="190" rx="30" ry="30" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 190px; margin-left: 101px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Solved</div></div></div></foreignObject><image x="101" y="183.5" width="58" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="381px" height="81px" viewBox="-0.5 -0.5 381 81"><defs/><g><g><path d="M 80 40 L 93.63 40" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 98.88 40 L 91.88 43.5 L 93.63 40 L 91.88 36.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><ellipse cx="40" cy="40" rx="40" ry="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 1px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">uninitialized</div></div></div></foreignObject><image x="1" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 180 40 L 193.63 40" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 198.88 40 L 191.88 43.5 L 193.63 40 L 191.88 36.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><ellipse cx="140" cy="40" rx="40" ry="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 101px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">idle</div></div></div></foreignObject><image x="101" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 280 40 L 293.63 40" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 298.88 40 L 291.88 43.5 L 293.63 40 L 291.88 36.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><ellipse cx="240" cy="40" rx="40" ry="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 201px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">playing</div></div></div></foreignObject><image x="201" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><ellipse cx="340" cy="40" rx="40" ry="40" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 301px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">solved</div></div></div></foreignObject><image x="301" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATgAAABECAYAAAAV6ClkAAAAAXNSR0IArs4c6QAADppJREFUeF7tnQOwNEkWhc+sbWvWtm3bdqxte2dtI9a27Vjbtm17t76JyogbN6q7szJfTf/x3rkRE/+87ryZWae6Tl9m7yeLETACRmCXIrDfLr0uX5YRMAJGQCY4fwiMgBHYtQiY4HbtrfWFGQEjYILzZ8AIGIFdi4AJbtfeWl+YETACJjh/BoyAEdi1CJjgdu2t9YUZASNggvNnwAgYgV2LgAlu197axS7sAEn3DbO/VdLlF1tt90z8v3Qp55H08d1zefvmlZjg9s37si/vygTXdndMcG24dWmZ4Lrg25PKJri2226Ca8OtS8sE1wXfnlQ2wbXddhNcG25dWia4Lvj2pLIJru22m+DacOvSMsF1wbcnlU1wbbfdBNeGW5eWCa4Lvj2pbIJru+0muDbcurRMcF3w7UllE1zbbTfBteHWpWWC64JvTyqb4NpuuwmuDbcuLRNcF3zNyqeXdHVJZ5d0GklHlXRESf+W9CdJ35f0FUnvkvRmSX9uWOlgki4m6RKSLiDpOJKOIemQkn4r6TeSPifp/cM+3iLpV5VrbCK4l0u6dpjrq5JOVzl3HvZ5SWcKL74yzT017UkkXWG87lNIOuaILdf8a0lflPTO8ZrBoEXA8CrDXFeVdJYR28NK+r2kb0p6n6QXSPpumNwE14J0p44JrhPAmeqnHcjsSZIuPkOPB/MRw0P6OEn5IVk1zZUHInuYJNarkb8M5PdUSQ+X9McNCpsIjq4GSDkKBAfRzZFTSvpGUmBuOiem5HiSHjJ8OdxY0sErFuKL5DGSHivpbxXjy5BzSnpeBWn/R9LjJd1bEv9vgpsB8k4NNcHtFJKb57ngaDVgqbXI60er779rlLmfj5J095YFJH1J0mUk/WSN/iaCw7r5maSjhzkeOJLPnG3dP+lgYUJiWLlZzirpbZKOPWeBcSztUpeV9LsK3fNKes+AMdZarbxmIPdrDu1t/0rE61atWgQ7xpngOsCboXoUSV8bXZmixoP6xvGB+fbomkIOuJJnGx+Kk6Y1Hjz8/aA162Ll3SW9j6Xy0tHd/dForRxL0rkkXU8S7nIU9oJb+NcV62wiONSeIelWQf/Lks4wAy+GohNd2ycPJHTHiTmY96ODJXaE9N7bBwv2VSPuYHC0MSTANRMaiIKrfm5J/1yzR9x7LErmifIBSS8cLVQsYbCFCG8g6VTjwLuNFvWhg6IJbuYHomW4Ca4Ftfk6WFSPDmrEgnBTv7BmKtwsXK77hDE8QPuP8bOseuEx9hPv6YfHmNUqi4w1sJSwsKLgrt6+g+DOP8T/PpT0Tz3hcq66fIgNgotyjqGp/9PptUNJ+pSkM4bXcbGxmIizrRLI9ymSDhEGbPryAJPbpgn5MnnCikX4ssLlh9yIoR4mrWeCm/8czdYwwc2GrEmBoPNFgibkwQNTI68dg9llLDEmLIYsnx0D3uX1bw3xKkjhDxWLPEvSLcI4YkYQ6RQx1lhwfK6+N85RpoVI0a0RiJ3xRbB+p+KJdx7jXGUc+4boIfZNAjlh8RbBeuOafz6hiAX+yzFBU94miXCTTYtIerGk60+MM8FVgNc7xATXi2CdPm7fycJQLJyP1KkeSFK4O2RW+e8zw4P1g6SLy4UlE+Uag/tJ/KdGcKuYO8aWOBIJCyRLDcGhQ2LkXkEZa/XMNZsZLT2SDEWwYpkvCp9dMpYnDy+ucmOnlkUf4ixuJGPuMSYe8vgbpi8VEgZkaL9TcT3EDRmHBRfFBFcBXu8QE1wvgnX6X08P0nUkvaJOtWoU2TqsmSJkXiEtLJpaecNQNnKlMBiLkFhgllqCI7ZH0iIKpIVluU4gQWJiRSCTE0v6YVKi9OWD6TVKRCDqWrlTcjHZb3R3yzyUp+D2FqF8hfKQWsnYomeCq0WvY5wJrgO8GaqUNpCpK0Is6Xwbgtozpj/QGiSwXYRatOvOmWBwwW4z1Iw9LejgspHxzYH3WoJjKmrOYnJhyhLL28yWH0H86N6X8fccrKJHBuWWejtqEGP5CmR6pIm6Q8YwtsgcSxGdWw7Jo2emCzXBzfyAtgw3wbWgNl+HwldIJwouGy4gRbarMpY1K5EoILB+uDCY2qv48NfMA4kQK4yClYK1EmUOwWUSwjKjpGOd4M7F7PFNh9jY8ycUXjcW25a3yBRPxbrWrcXnH+yj+5jDByQLSO7wb5E5MVR0pqxNE1zNp7JzjAmuE8BKdUgIK+5SE+P/Mcbj6CiAYD4x07Wk9isHxufE38qWTjQR26MjAAJuJTjmxGWMnzNiZqtiV8QbPxkWowCXspmp4mPIMsb0Xj245U+vvB9xGEmAE4QXbj78/ZzwN+9RXhPlihPFzOuWPr6kH6cBJriGmzVXxQQ3F7H28dRpvShZHVOzUXD6jpFYIJdNnQVTFf+UoLx35lbJFOZiV2rGXtZBcKgSJ8OCKULigWLkKaGr4K7hDeKUxCunhCwtsbmdFkp62EeR7MbyOtYurnOt4PbmbLYJrha9jnEmuA7wGlWJjVECQV3YJsG6wxXjgSPoPyXZ6mFMy8ODC5bjbcTlKNqNMsdFRY+aszgH8Uf2nIXPItnhE4Y3Ljd2KExdN4kUenh3Wh4q6QFh0il8KQrG0q4VLPjcgdFyj2rX87gRARPc9j4KPDg0a9NfmbsJ8q4IfkNyxLRyT+NUiQgJh4/NvDSKZiHUKJATNXI9BEflPy50jGFNZTvZcyyd+cXoOk61ZrEf6tJopN9poXA3doPQ8ZF//WouOVF+k+Osc+fY6evcE/OZ4PaN20yMhlM/iNFxAsiqB5dM3K3TlqnHoh4sCnPRMzlHsIawiqJMlbPMteCY703jCR9l7uwG8jqHENwhLP7EVPqSr4Vyk1gD19LvWoPPVLnLRcdTWGr0GUObVz6txQRXi17HOBNcB3gLqXLMEVbDzYbjdigwje1ELHnp1IZEvRvWTpRrjX2Yc7aIVRWP90GX0hZ6OqO0EFzOIuPe4eYV4ZoJwh83vEYN3iq3nGEUNseeUmoBY/xuzrWvG0ucj3hfFOoFIe1amYrjmeBq0esYZ4LrAO8gUOUBJuEQT+agaJSzyIpwDzmHjEB2kTltUUXnkhP9m7RHUe0fpYXgKGGBhGNDPG1RpXj3QiloX1PTRvIjJiCIVV5tgXvC3ukljc8Klia9rLXC8VWcBhPFBFeLXsc4E1wHeAeRKnVgzw1rcRQR7T9RKDGhB7MI/ascqDlHsH5i9pATOMis5uOZWgiOfZBBpuWsCCeDUDCL5Eb2mjq+3IdKgmKJrCr7o9QFQi6y7jCCKcxzby1jTHBzPp2NY01wjcA1qh1+LBqdo57r02i/ym4rBcOQQhFKS4j7cAZZrVBWQmypCH9PHczZSnC41tHd5bQPXkOoMyu1aBAqZJLrxvJ1TAX/N7m1tVjkcbkTZVVL16r56R/OBc4muNa7MUPPBDcDrMahHLEDcdAVgOVFQmHOUdm5zg1dyCvKVIznRqPVVLNtDgKgXzYS56oOglaCo1Tip2OPLHv6+3i2GuUyMdZGsTOJlhrBfY7lNi9JVuKmOcjwUs9G9pbj4Vl76vSV3LNKJhv3Hcw2Sc4Ol/EmuE3I7cD7JrgdAHHDFBxvHY/Voe0I8qiVfJYchbPErLLkglpcNqyGnBnNenwGiA/FRntiepDx1FHerQTHusStbhc2gAXHgx7PowMrjiKqEWJhZF+j1HYZkNigiT668qtceyzK3MTPSS10jKwTykO4L/mATXRMcDV3uHOMCa4TwAr1KVcK0iPmBZGsE2rkeAhjnykW4VRLEmRGdjJaYZx0y0OI5TQlzEs5Bu1JUWgOf/YKnR6CI3Ma6/OoOSN2WE7moFaM1izifzVC7R6tXfGHabAMyUDTm7pKSNpQ3xeTEtTbUZuYe2/LHHwJkCyIwiGmHCs1VavHFwRETckOJSL0u8bj6k1wNXe4c4wJrhPASnU+6LiMUcjMcWQ5DzxlCPxNMSxuE24Xv43AQxCFBn0ewlWxtfsN5/5TiR8FEuWATGJeHGDJPYdEsAJpTo+dA+jlLG2+xB6CY654Nh7EGxMmZEZpD5sj1KmBYT6ynDISjiwnXoZbD8FQCsNvY1BGk38bY9X5d2UvhAqYC1KNwjHmHKTAv5ArvcG0pmERlz3xBYKVGnteOU2GLyDLggiY4BYEN0zNw8UvTc35Na28M+JNuHT5XLQ8jjYjjt9uEawe3Od1v03QS3AQMEQ8JZA6ZTFzBeuVRADE3SKcvBKTNKvmwBqmPxb3tlbKKSe5MJkvmHyeXe2cHleJgAmuEqgdGEaQnfP5ianFurZNU2MVELuCWDY13pe5IAoa2mt/6IX4EqUMU8cS5f31EhzWaa6tYw3q5EjAzDmkM+6NImF+kAeCzlnmVRhjkXGK7xxSJWxAiCBbvnkNssEciV5+NjBnUqk7fPemm+/3+xAwwfXh16JNqQgtWVhzuFecfXbkMc5GLyjxJ8omePjI8OEy1vyuQt4LVgbZW6w+XCYIoGRfcdkgFFwkHjIe8NqSkl6CY59TZRO5B7QFW3Qoq4GEiH1BplwzbWhgy2kpWFK4r1h8WFC1vzUb94PriTWHG8o9xC3FSi8//ExdIl8W8VgosrTsqQjxP4qTLQsiYIJbEFxPbQSMwHYRMMFtF3+vbgSMwIIImOAWBNdTGwEjsF0ETHDbxd+rGwEjsCACJrgFwfXURsAIbBcBE9x28ffqRsAILIiACW5BcD21ETAC20XABLdd/L26ETACCyJgglsQXE9tBIzAdhEwwW0Xf69uBIzAggiY4BYE11MbASOwXQRMcNvF36sbASOwIAImuAXB9dRGwAhsFwET3Hbx9+pGwAgsiIAJbkFwPbURMALbRcAEt138vboRMAILImCCWxBcT20EjMB2ETDBbRd/r24EjMCCCJjgFgTXUxsBI7BdBExw28XfqxsBI7AgAia4BcH11EbACGwXARPcdvH36kbACCyIgAluQXA9tREwAttFwAS3Xfy9uhEwAgsi8H8AEIljoW6tTwAAAABJRU5ErkJggg=="/></switch></g></g></g></svg> \ No newline at end of file
diff --git a/docs/img/puzzle-module-top.svg b/docs/img/puzzle-module-top.svg
index 79c16ed..bc65730 100644
--- a/docs/img/puzzle-module-top.svg
+++ b/docs/img/puzzle-module-top.svg
@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="313px" height="133px" viewBox="-0.5 -0.5 313 133"><defs/><g><rect x="113" y="0" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 114px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Puzzle module</div></div></div></foreignObject><image x="114" y="26" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 153 111.63 L 153 86.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 153 116.88 L 149.5 109.88 L 153 111.63 L 156.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 153 81.12 L 156.5 88.12 L 153 86.37 L 149.5 88.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 113 120 L 193 120" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 120px; margin-left: 105px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Puzzle bus</div></div></div></foreignObject><image x="46" y="113.5" width="59" height="17" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 193 40 L 213 40 L 226.63 40" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 231.88 40 L 224.88 43.5 L 226.63 40 L 224.88 36.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 40px; margin-left: 241px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Puzzle outputs</div></div></div></foreignObject><image x="241" y="34" width="72" height="15.75" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASAAAAA/CAYAAABAdBV6AAAAAXNSR0IArs4c6QAAEOdJREFUeF7tnQesFUUXxwc1KEGxBbEQNCaCvWDDgmIlgg2ViILYe9eoYMHeQRDQ2EVQUbFRFCuCgmJXiBEhVgKCRozYCcqX33yZm3njltk7u2/ve/dM8hJ4b2d25j8z/znnzDlnW6xYsWKFkiIICAKCQAkItBACKgF1eaUgIAhoBISAZCEIAoJAaQgIAZUGvbxYEBAEhIBkDQgCgkBpCAgBlQa9vFgQEASEgGQNCAKCQGkICAGVBr28WBAQBBoQ0PXXX68GDRpUFSpdunRR6667rtp1111V9+7d1fbbb69atmxZVVv1XGnGjBlqzz33rEDw6KOPqr59+9YzJDL2ZoxAbgTkYtSpUydNZkceeaRaddVVmzGE+Q5NCChfPENa++abb9SkSZPUySefrFq1ahXSVJOp++OPP6rHH39c9e/fX6299tqF97swAjI9P//889WNN96oWrduXfhgmsMLhIDKn8Xff/9d3XfffeqGG25QvXv3VkOHDm32BPT333+rZ555Rl133XVqk002UY899pjWaIouiQTUr18/tfXWW3v14bvvvlMfffSRmjlz5n+ev+WWW9TFF1+sVlllFa+26vkhIaByZ//nn39WJ554oho/frzuyOmnn97sCeivv/5SAwYMUHfeeaceMyaUmiCgrPYHwso+/vhjNXDgQPXKK69UVtIGG2ygnnjiCbXXXnuVu7qawNuFgMqdpJ9++knb3F5++eW6IaA///xTXXjhheree+9t2gRkls6iRYvUKaecol544YXKajrvvPPUbbfdJvaglP0lBCQE1NgINDsCAsBnn31WG6BN2X333bVxa+ONN25sfJvU+4SAyp0ukYCasApmL52FCxdqUXbq1KmVX0+fPl3tscce5a6wGn+7EFC5EyQE1EwI6I8//lDcgD3wwAOVFYVh79BDDy13hdX424WAyp0gIaBmQkCuXsmywhB99NFHV1ZYiO75xRdf6LY+/fRT3R7Xh1dddVWD1Ysln5u80LLddtupJ598UuHbRCmqXdquloC4APj222/V888/r9544w2NC/+n4CTauXNnddhhh6muXbs22pXy8uXL1bvvvqttgUi/n3zyifr111/VGmusoR1V9957b30g7bDDDl43pNVi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"/></switch></g><path d="M 73 40 L 93.52 40.52 L 106.63 40.17" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 111.88 40.03 L 104.98 43.72 L 106.63 40.17 L 104.79 36.72 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 40px; margin-left: 65px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Puzzle inputs</div></div></div></foreignObject><image x="0" y="34" width="65" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="312px" height="133px" viewBox="-0.5 -0.5 312 133"><defs/><g><g><rect x="112" y="0" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 113px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">puzzle module</div></div></div></foreignObject><image x="113" y="33.5" width="78" height="17" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATgAAABECAYAAAAV6ClkAAAAAXNSR0IArs4c6QAAE1dJREFUeF7tnQPwJEsSxr93tm3btm3btq13tm3bF2fbtm3b7N+Lqo3c3Oru7J6Z3en/ZUZs7O5MdXVVVtVX6dlPScmB5EByYIdyYL8dOq+cVnIgOZAcUAJcboLkQHJgx3IgAW7HLm1OLDmQHEiAyz2QHEgO7FgOJMDt2KXNiSUHkgMJcLkHkgPJgR3LgQS4Hbu0ObHkQHIgAS73QHIgObBjOZAAt4ylvYikd5qh/lnSYZYx9BzlBjnwPknnN/3fU9LDN/i+SNcPlnRv0/DNki4TeXATbRLgNsHV9feZALd+nu6EHhPgRlYxAW4Z2zwBbhnrtLdHmQCXALe399xG3pcAtxG2Lr7TBLgEuMVvYiaQALcjlnHtk0iAS4Bb+6baFx0mwO0Lrm//OxPgEuC2f5cGRpgAF2DS/2GTBLgEuB2x7RPgdsQyrn0SCXAJcGvfVPuiwwS4fcH17X9nAtwMgHuepBuY5+4u6ZHm/xeVdA1JZ5N0vO67Q0n6naSfdcbwD0l6rQtKHRrC9yQd3zS4rqQXT9hXX5N0ctP+hpKe33jeb4QJr9it6Qscb+qXm+5/VYA7Qgm2vLikM0g6qqQjSfqjpF9J+nZZszdJ+uZc5gSfe6gkAlIr3bULWn60+T9jvJ6kc0g6lqQDSfqNpC9Jel23554r6W+NdzHHG5V5nkbSESUREM2+/HDZFx8MjtE3O07p98KSTi3pyKb/X0v6kaT3S3qXpLnv4J3nk3S18vcxJTEn5vBdSR+R9NIyl7591xfoe4LSh53Xccu4Iyw5hqSfuoYn7M4C59fTqoG+9HvZbp7gzEnLXj1s2QPs1S9Iersk9iq8H6RWHNwTuwdva556mKR7SWKSL5F0obFOJb1b0s26jfqdkbYJcLszqA9A5wLcISTdSdLdJB0+sG7/kfSiEon+40D7OU04hIBcpQdJul8ZHwf4UiOdsqeIjP+qaXdlSc8qoDP0OPy9iaR/BQd+tDK2m3ZjPljwmU8UAH9PsD3NALOnS7pc4Jm3SOIi/0WXxfBeSRcwzywZ4LjMHlgEiAMH+MDl/KhyOf61r30L4HjoLuaBp0q6r6SPdjfIyQIvrk04IOdt3By2iwS4zQEcUga3HJLQVOLwXEzS56c+GGh/ZyexPaZcoADCuQPP04R9c/oOvP/QSZ9I/QBXNGidC/z2gfecquPd2yQh6UwlLgoulicEHkSaRsJEWonSNySdS9IrOokRqbLSUgHuTJ1GCHAfPcoA0+5j5VL8bevZ1qZAYruHafzCooZepXz2/U5Mf1XZ/KgOqDrnlHTNxg2KOMng/90z8L0FcKjTjHMKoTp5afVW3SI8rdHJpvufKsEdult0JAkOqSXWg/X8eBHvDyfpFJKuIOnyDiQwO5xV0remMC3QFnB5vGn35KKGYQqByF3kDxck+bZnKRIL6pql/YvKyjyRVFFXMG98sqjeaByXKHOz+xzwOaUkQKKPML18rrGfOUyAymcl/bKMDxMLUue1GlLezTs1+5kjPEG1RTW1hJngGWWdOGOo26jdV+9U4QuWhlxeB+0ED1T6SksEuNMW9dvnVr+127+vLJI60hrnl71w7fK35RfrwUX+D8/rFsB5GwmAVu1kDyli5B4dFRX2NeVmse+5RVms1jrvLYALnLvdmqD/o+db/rwxqEJE3jW1/6kAh7rD4ar036I2IZ1zwFuE9IT9FLWsErZFQJ7n10W3c5IN7+Dd2NWuVOxY/l3HLocA4KmEqortC3CgEAEXbMsmw8XMhWwJVQiAbBFrji3NXm6otPAT+18fcVGwR05iGvxJEge4ZauiWWtsACgqaJ/aBchxSaEyI7UAfpWWBnDMgQvpdGYOSOXYITl/fQSmPEnSQUyDB3T/vr9/oAVw3khYn6FKgTUOt15+FElfdocE4zCL3KJtBDgOOKoZEkAlpAlUolGj5sCi1K/m9D8F4JCYP+3GgQ0VyXyMkERxFCEZVMK+BfCti25TNqfv75JFJex7D44vHGCecDSdubMz/mVggKiaVtIBVKsk5B/DDvYG92Gf5O6fPbGkL0o6pPkCSYwD2SION1JJJeZyxh4nin3+xpKe3ehwaQB3R0mPNfNA08OmyB4cI0wAmDcqIXQhiOFU2kVRgPtBsb/9feyt3c2DquFLtqASsHietg3g4AfqEYetEhIPdg4Oxao0t/8pAPec4k2sY0XVAgD6JDc/Jw4kDqJK2EYuverEzfMtgANQUJOHCEmFC8bvWQAJyWmIABhrWsAbh+2rRah+dr5c0FxuUf7hEcbOWOn3xYngJTIOo5fs8AK3QNyPEx58pnjE7XdLAjjmgJnASrxR+yhz5nkcTTaKAmcaWsouigIcXi68XRFquaTZ1E9pPLxtAOdvBYaMRIuTZR00t/8owB28qC1WgkDywQgfJcJIsGlU4lbFy4fNaR3UArgISPHun5Sx1HHgDMH71mfjre1QY7F1WcJT50ELEGWe1ouHlGFthmM88PyjfWt+t+w0HRx4lRgLGlDTWN546R06z/Pj3OdLAjgckB9w4+8LPenjuecB0rNVd5uep5aKigTAjRElD1ws5K0bD28TwKHa4Sm24QDEHlFQMBpWMMSfVfqPAtzZO8M6hvBK2M5QtQGCKHHpEfNkPVpINEhy6yAPcIwRBwK2lzFC9YaPlYiLw243RngovVMBBwvGa0vYRt/hPkNCGHJItN79c2emwTaEjcgSZwKQq4QDCEkxSozLa0VLAjiv6X2lxBhG5087NEOeq8ReYl2xfR5AEQmOw00w7z8nvBmjL4eyEiEA1p1dP98WgMODw+GxYTB4EbmNcbKsSqv2HwU4b8DHdkiQ6lTCwEuYSKX7dHY5HEzrIA9wPywB45G+CaI9j2mIQ8xWj+3rAycFDglLqKioqpaIHrC2StRKPNJTnSzeM9pSwX1wOA66GqkQ4QVSJnZHeyEvCeCw617RTJQY2+tEJm7agF/wAC96JfYHYTcHUATgCBOYEqNDvwRdElBZaQ/RsXyxLQCHCkf0vKWrdq75V09keF/zVfuPAhwqC2J7JcINrD0tOh1sSLbM9JzN1/cuD3BTJBcPCnvYXHpe2orEbwEcdjrrEMBhRnjGVMLbiie0EpendSbwOecKp0QljO3Wdhd5J+trbVhLAjjMIAgQlfB0W5U9Mn/aEJhuL3GCsnc5YCIAh9pGUOEUYrGwXVQCyNCvPW0DwBG/xAG2ROySDbOYMnffdh39RwHOp9mtMm777Drr6nuAIyYvGozsAY6MG+LoxigKcGRSEG5SCW8etqKphM3OBhMDRD5I3quxzTCHkRdjNsLrWmlJAEf6Gfb6ddNuqX8RgCPtyqqbkQF5O16f12pfA9yJikEdvb0SOj23bW/6R4QBpc26+o8CnBf7Jwx1sCmqoQ9Gndv3NgMcQG5TxVDVCRaeSqjzhOZUwgbqo/TJMcX0Uwn1+BETX+RV9iUBXA1gnjjl0eY19e+AhhGAI6J4LD/Qv9UvMLeVjSur7fclwBHrxQ1N7Fclgk2J3ic0YFVaZ/9RgCPyG9V63YQ6YY37q/S/zQDnQ0RwONj4uei8fbA8sVl4oi1xgVrb0ZxfxEL6tft3SQAH6PeF6kT53GqHmYZohTDAYTC1Cb2Rl3sVtc+Oty8BjtsSG46laEBnhAfr7D8KcN72STJ2pDhCZD7rarPNAIepApNCJYzV1qkR5QE5qDh8Kn29pMTZ59FqyBeuNJRd0fdeLmKqm1RaEsB5+yGZJfBgrRSR4Obc3v6gEWxqbQV1EqsCHJ4xPGSV+soleaa1UqWiIQeRBVh3/1GA84USsNEQ4rNNtM0A50M3CCT1+bwRXnqnEvmyhPBY8nt/N8kj8pIuzMTb8TYFcDgyfBmtVcsl+SyOOU6WUTZFAI5IbJ/oPNYxoj2HvFJfHqdf5ClBqYwdO4YNao0AXCtVilAFYpCiQZZD899E/1GAw2NKJkIlIv8JHt0m2maA85VOSP/BTjYWSOz5S/wkBSgqYTogh9SSVy+xn5IWFyXKXxHKZGkKwGHgj4ZA+fhK3rkqwHmHztT5h/gUATg6wg07pT4YidDWa4q6ZiuU1MEhulvv0hQVkeRmWxOMPscArpUqxeYlL3GVQoV1PpvqPwpwSMk+IHtqdHho46zQaJsBjqBun5JHHvUUmyzxaaifVijwRT1hH4VZr2/4OJSz3WI3pgccgBGAw/5HFoglJFN/fvqW1ae6rQPgfB4qYLt2r2oU4EjuHaqkYBkDGCIRWSKAz4di8P2nnAqFc4Kg0gh5BkUArpUqtU7df1P9RwGO6gp4p6iAWgmpxCY0R3i7yTbbDHAEZCP12uDZqd7NVgoSn/kEckDPVsommBije7SgA4nmu4zpZcH6JDjm1craoGpKhAhU9sU4V5XgWlLh1Iyp0bFHAY6cMW63CBGbRNJsJSQkPKg+apzvvVseLxbliseIDUgQpg1yHAO4VqoU8+ImnKqCtMa3yf6jAMe4fKkkypFjiI4USqjzYh1Q/zE18MdfWGPrM/T9NgMc46ZcEeV6KmF7IiUoukd8LCJmGAJ6fd5rK2d1qLSY5SkXGHFk1knB930AxzkH4MjKqERRW1uNo2/N0LAInfJVdlcFON6HBIkmVol6fhQwjRI14pC4cQaxT8mYwqS2i6IAxwORsjkwEOCxv7Mw5Mnz4SSEaVBBtQWGdtyt24vv+1RUbjBUN5uRgaSD3c2n8ESZa9ttuv8pAMeccOp4ftkqzUNz9BcUeams55RUvaH+tx3gWqpfVAomxIjAeAsGQ+Ef3pQDaLF+Xtry/CS4uZXbPfQuQMAG7GPktyEmrTWjeAOg0Qr0XwfA+dRCxhAtvMBvdXAZ2fS2PdLdIgBHdQVEZ250YqyIi2sRh/xlLsWHdgRK9hWva20mHBLcoK0fFsGhACiinrIJOMg20rwP4FqpUpTn8XW/5oAbz2y6/ykAx3h8yhGfUcaHqigtvvI9cXskQOOqt/uirxLMXF5tO8AxLx8wjfSGA2fITEPRTjzxNraL8CgkNc5Oi3x1Y9oMFe8EcNj/NaULgCSYvNIQwLGuvirOUI4xVVoorEkOOWCIfczObR0AhyaGh9kWGWB/kubZMmnVeSK54kyzThly5rlgdrvcIwBHPiaewRrJTlUJkBLxEi8OL2NxEa+9kXAsSLhVE4pJ4NDAy8JgqTKBwRYDOsBX8854H54qa6ht2QoBZbxYlvByRcs/+Y2JRGrVvU33z/unAhyePzalD3Ggrh98Zf6EGHALspG5yfmlNCt5817Efi6oqcnmQ+C3BIAj6wCJH95YwhGFGoVDoFbTpaoH5d6RPOx5wgPL5csB7iMuFTQen+uNBvPysoa8hzMGUHKg6/4HAFgXm6BO4QH7gz72vQASVVFsFVy+Z56cZ1RxwIWzzriRjNDI+Ixz9nq3P1C7Wz8qNfVXtcj1Rer1JcvZv5xb8tixSxIUzRzAITzS1s7MPJpzjwAcUg5qC4diSmUKNgGDGQu9wIOJsZPDFqVaJZWcUZJrK7Vq4PsChNF39LXzP7e26f7nABzPcCiQhm24wpS5syZIuX3Sx5S+bNslABzj5TAhTdmE+OicMX/Au4hnHoDEATElnAebGGoje88WtRhzmFHX0ZdtGpoTdkOKUACmgKMF4r4yUlMBjvdjv8Ye38p2ivC8t9p4BOBqDBv18FHFIlkNVAbARhAtkohjAXF4LN4OOxCSF0zk9vI/cdhKvt40AG26/7kAx3PcelQXIWPD1u4f2jSk0CAFUPM+WsU2sglrm6UAHOPFiA0oULct8rOB8AszDapf3+8wtHiFE4MKGJGiFmhQaC1Ied4WPVY+ivPOfBifl+T8uDi7aES1WjJVX+xPD/SFz8wBON5NKAt186hqPDa2OlakO/Y2JembFAE479nEboY6QwUIVFLUIaQ04mzwaGD4Q9qbSiS8MzkChKnKyeZiU+EVobAfMT+U40bNqgTY2bCS1m8PbBqANt3/KgBX+QRvKVoJb3HFY0tBwuOSwASAcZvfocBWyk3aZ6ebuqat9ksCuDp+smVQQamRBxghbRFoC+8AGqQb9idggNd6DnEWyfmmgCdSN2oy76g//Iwah3nBSoXsd1unj0vJpoj1jYNzi+aDhoVUVi8/QA0gYw8gzOwqHFnea9PWAGPG5GkuwNV+EKQo1cVexcMKrxkfZiFwBlUa9ZUxEgUxaD6JANw6S+XMWfh8JjmQHEgOzOJAAtwstuVDyYHkwBI4kAC3hFXKMSYHkgOzOJAAN4tt+VByIDmwBA4kwC1hlXKMyYHkwCwOJMDNYls+lBxIDiyBAwlwS1ilHGNyIDkwiwMJcLPYlg8lB5IDS+BAAtwSVinHmBxIDsziQALcLLblQ8mB5MASONACuCWMO8eYHEgOJAdGOZAAN8qibJAcSA4slQMJcEtduRx3ciA5MMqBBLhRFmWD5EByYKkcSIBb6srluJMDyYFRDiTAjbIoGyQHkgNL5UAC3FJXLsedHEgOjHIgAW6URdkgOZAcWCoHEuCWunI57uRAcmCUAwlwoyzKBsmB5MBSOZAAt9SVy3EnB5IDoxxIgBtlUTZIDiQHlsqBBLilrlyOOzmQHBjlQALcKIuyQXIgObBUDvwP+QAWkI4GNlsAAAAASUVORK5CYII="/></switch></g></g><g><path d="M 152 111.63 L 152 86.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 152 116.88 L 148.5 109.88 L 152 111.63 L 155.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 152 81.12 L 155.5 88.12 L 152 86.37 L 148.5 88.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><path d="M 112 120 L 192 120" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 120px; margin-left: 104px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">puzzle bus</div></div></div></foreignObject><image x="47" y="113.5" width="57" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 192 40 L 212 40 L 225.63 40" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 230.88 40 L 223.88 43.5 L 225.63 40 L 223.88 36.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 40px; margin-left: 240px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">puzzle outputs</div></div></div></foreignObject><image x="240" y="34" width="71" height="15.75" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARwAAAA/CAYAAAAyu3fMAAAAAXNSR0IArs4c6QAAE+NJREFUeF7tnQOwJTkXxzM7a9u2bdu2rVobtUbN2rZt21atbdvmfPXL7uk6N6+Rvn2775vvnVO1tfVudwf/JP8cJdNv4MCBA52JIWAIGAININDPCKcBlK0KQ8AQ8AgY4dhEMAQMgcYQMMJpDGqryBAwBIxwbA4YAoZAYwgY4TQGtVVkCBgCRjg2BwwBQ6AxBIxwGoPaKjIEDAEjnC7Ogd9++80NM8wwSQumm24699JLL3WxRVa1IVAvAkY49eKbW7oRThfBt6q7goARTldg/7dSI5wugm9VdwUBI5yuwG6E00XYW6p+9NFH3Xzzzed/O+yww9xee+3VW5pWWzv++usvN9JII7lffvnFLbXUUu7222+vra6wYCOcxqDuWZFpOF0E/7+qjz76aLf77rv3KcJ5+umn3RxzzOH7bITT/TnYWAuMcBqDOrOiVVdd1V133XV9inBOPPFEt+OOOxrhdH/6NdsCI5xm8U6rbeyxx3aff/55nyKctdZay1155ZVGON2ffs22wAinWbzD2t5++203+eSTJz/3FR/OBBNM4D766KPuEs7777/vJp544gT8zTbbzJ199tn+bxbGRRdd5K6//nr3wgsvuC+//NL179/fjTnmmG6mmWZyK6+8slt33XXdkEMOmTuD1l9/fXfJJZck79x3331u4YUXjpp1ww8/vPv555/9u6ONNpr76quvenx36KGHuv322y+qvKyX6Cft1FJXuVUI5+WXX/amwN133+3ee+89jwdXG40xxhiOCbXYYov5cZl55pkr4RH7MY7IG2+80d15553u8ccfd1988YX7+uuv3dBDD+3Ha6KJJvJjveKKK7pZZpmlsNi33nrLTTHFFMl7Cy20kLv//vsLv+MF7Zfh75NOOsltt912/ltwAqMYwZn88MMPJ69usskm7vzzz0/+/vDDD93444/v/2ZdsF4efPBBPx7M1VFGGcWNN954bskll3QbbLCBm3766XOrravPVErdzJkY+fPPP93ggw/e49XPPvvMa0aMA2XBAz/++KN/Fyf0ZJNN5maffXY/xsy/NEmcxkyO0UcfPXlntdVWc1dffbUHEjuX3SBPpppqKnfhhRe6OeecM/M1I5xWImuHcD7++GPv5Lz88ss9wRTJGmus4Y455hhPQnUJ84ToTtEckfqXX355d9xxx7VoF2Hb6lp8VQhn++23dyeffHLS1BdffNGRrLnnnnt6kssbDzboHXbYwR111FF+s06TuvpclXDYTPbff3937LHHut9//z1qGrHRnXvuuT02l4RwYKoRRxwxKWzxxRd3Z511lmcsyChGYLl7773XzTrrrKmvDwqEc/HFF7v11luvpf2d0HDSyi1LOGQhL7PMMok6rBvJbsqE/+6773pgzy6LJjT11FPHDGOpdw466CB34IEH9vimX79+btRRR/UT9KeffurxnM3tlltuydyg6lp84DP33HP79nz//feOXVsEzYc2i8w222wtGvmuu+7qF50I2s+1117b8lsReBtuuKHXksCnKZKlHrSON954w6G9vPPOO0nVww03XKKlyY9oL0KKzKlVVlnF3XDDDaldQ7v5+++/U8kW7faee+5x8847b/JtQjjE5KlchEEZdthhPYHwf9idiieZZBKvQjEhLr30Us/4VCgyzTTTeK0oTSWrm3AAR7elaPDx1J966qnJa+OOO657/vnnWzQ9HtZVbhnCQX2dYYYZEgcn7WIsWOxMppFHHjlZRORVHHLIIS0qNKo/E0lvKkX4FD1nQ9pyyy1bXlthhRV8BGTBBRd0QwwxhH/GhnXTTTf5tmK6i2CS0yatWcuzughHNxYTaIsttkh+KvLh7LHHHl5DEdl777197g4yzzzzuG222cbn9GBCfvvtt+6hhx5yRxxxRI/jKrgVcEE0SThZuBaFxUOMRhhhBLfLLru4lVZayWHVwA2sj08++cSR0wQfYFaKMO8Yy6GGGsr/lBBOOPnxx/zxxx/eBsXXou1pDRQ2+3LLLedQu0RoJD6gUOomnKIFop+zu6Laiww22GDurrvucosuumiZYnq8W6bcMoSDictuKrLAAgu4m2++OZNAKHv11Vf3WoQIC+KUU06p1D/5GKfjtNNO6214kcMPP9ybF1nyww8/OHwxzz33XPIKO/4FF1zQlcVXlnAwGyEQEVkj9BniSdNa0PCYZ2iYIviz0DKYc1qaINmwjiLCwUXy1FNP+WaiROCfQ/PLEsiHDQe/mcg555zjNt10U/9nJuHIy4899liigmZVsvPOO7vjjz8+ebzIIot4zSiU3kI4qNEzzjijd3qJsFsNGDCg0mIsW24s4WBKod2IoPqj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"/></switch></g></g><g><path d="M 72 40 L 92.5 40.5 L 105.63 40.16" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 110.88 40.03 L 103.97 43.71 L 105.63 40.16 L 103.79 36.71 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 40px; margin-left: 64px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">puzzle inputs</div></div></div></foreignObject><image x="0" y="34" width="64" height="15.75" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAA/CAYAAAAPKRaqAAAAAXNSR0IArs4c6QAAEe1JREFUeF7tnQPQJTkQx3vPtrVn27Zt27Z9t1dn27avzrZt27axV79U9VS+7CDvzXs78+10V13t3b4kk3Q6/zRzffr3799fjIwDxoFGcqCPAUAj990WbRxwHDAAMEEwDjSYAwYADd58W7pxwADAZMA40GAOGAA0ePNt6cYBAwCTAeNAgzlgANDgzbelGwcMACqUgT/++EOGHXbYZAbTTTedvPLKKxXOKP7TO++8s5x00klJhxtuuEFWXnnl+AGsZS04YABQ4TYYAFTIfPu05QFULQMGAFXvgH3fNIAKZaA3A8Cpp54q1157bcK9ww47TOaff/4Kudm7P/3PP//IyCOPLL/99psstdRScscddwyUBRkADBQ2p3+kNwNAhWwbJD/9zDPPyBxzzOHWZgAwSG7xgIsyAGjIRkcs8+STT5addtrJACCCV4NMEwOAQWYrSy9krbXWkquvvtoAoDQne9EABgC9aLO6PNUJJ5xQPvnkk+oA4MMPP5SJJ544WeZmm20m5557rvtvBPWSSy6RG2+8UV566SX5+uuvZfDBB5exxhpLZpppJhf/XXfddWWooYbKZdP6668vl112WdLm/vvvl4UXXjiKtSOMMIL8+uuvru3oo48u33zzzQD9cEQdcMABUeNlNWKdzNOnbo1bBgBeffVVIfZ+zz33yAcffOD4wdMOY445piBMiy22mNuXmWeeuRQ/sjrH5gHMOeec8vTTT7thJp98cnn77beTIV9//XU555xzBDl47733nANspJFGkokmmkgWWGAB2XrrrWXaaafNnf9FF10kG2+8cdLG378vv/xSzj77bLnzzjvlzTfflB9++EGGH354GWeccWS++eaTNddc09nbRTTBBBPIp59+mjSLfULDt+vpvNpqq/VwnE4//fTCPsbQ33//LUMMMcQATb/44gunOTzwwANuLM7mzz//7NriVJxssslk9tlnlxVXXNHJREiJE/Dbb7+VMcYYI/ldJ8uBX3XVVeXdd9/NnedUU00lF198sbDhWWQA0BNY2gEABHGPPfaQK6+80h34IlpjjTXkuOOOc6DQSYoFgEUXXdQdcIiD9/nnn7t577fffnLUUUfJf//9lzmtPn36yP777y+HHnpoZpvrrrtOVl999eT3U045Rbbffnu56qqrZPPNN5dffvkld9lLL720ACJcZllURwAganDggQfK8ccfL3/++WfU1nIZnH/++TLLLLMk7RMAADVAX6XFF1/coTPoATjEEIhz3333yayzzpravDcAwKWXXirrrbdej/l3QgNIG7dVACBLcJlllklURX+So446qjtY3HIhjT/++E5TmHrqqWO2MapNLABww951111uTOSD+XFATzvttKjv0IiMwx133DG1/c033+xuNyX2ipuVSysPXPzBZphhBnnwwQcFHqZRtwCAeb/11lvC7Y4GpISWwjd94nZH64bY51VWWUVuuumm1Ply+//777+pF8Qwwwwj9957r8w777yubwIAqF98WGnuueeW4YYbzh1o/txhhx3cRyeZZBKnXrzzzjty+eWXC/FgPqY0zTTTODMhTV3pNgDAGH8uRRKG1/X0009Pmo033njy4osv9tCElOHdGLcVAEC1Q1BRa5XYi4MPPtgdgFFGGcX99Y8//uhiyP369euhXiJQCJEP8kX8yfs9FgCWXXZZuf32291QQw89tLtt1157beF2x2xEfefAImNoB3fffbccfvjh7t+VMP8+++wzGXHEEQeY0m233SbLLbdc8vdbbbWVU7O5tNB6dt11V1liiSUEEPz999+dbAI+AIdPW2yxhTMXBiYA6Lc4S1NMMUXy6aIwIKY581WCL6xzpZVWEjRxeMlZgGePPfaYO6MPPfRQ0h5Z4JvsRwIAoTBiz//111+Ocahw/gR9JoHubAAqiRITxIcQUrcBoBWBvvXWW2X55ZdPugw22GBO+FBZy1Ar47YCAJhk119/fTI1bORbbrkl80AzNqox81HadtttW7p5OwEAyAaHVAkz4Pvvv5drrrlGVlhhhdRPfPTRRzLjjDM6MFO68MILZaONNhqgPWCHVqSkcss+ckMCHmmE+gxIKnG7vvbaazLllFMO0LxbGkC7AOD7Vbhon3jiCZltttkytwsw4LLDPFI677zzZNNNN80GAG34+OOPC9pAHu2yyy5y4oknJk0WWWQRpznUFQBwnCBg3KpK++yzj7t5ylCr48YCAKo/t78Sjj5uc/7MI9Rt1H7VGoYcckh3K/i+nnbXG6sBALI+CPE9Yt5olHm09957Ox+BEjf7mWeeWQgANMCex9mYp+1wKDg0zz//fDLmIYcc4uzqkOoE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"/></switch></g></g></g></svg> \ No newline at end of file
diff --git a/docs/img/sequence-puzzle-module-init.puml b/docs/img/sequence-puzzle-module-init.puml
new file mode 100644
index 0000000..3d2fa56
--- /dev/null
+++ b/docs/img/sequence-puzzle-module-init.puml
@@ -0,0 +1,17 @@
+@startuml
+!include style.ipuml
+
+participant "main controller" as main
+participant "puzzle module" as mod
+
+activate main
+
+main -> mod : MAGIC REQ
+mod -> main : MAGIC RES
+
+|||
+
+main -> mod ++: STATE REQ
+mod -> main : STATE RES
+
+@enduml
diff --git a/docs/img/sequence-puzzle-module-init.svg b/docs/img/sequence-puzzle-module-init.svg
deleted file mode 100644
index 2e8db4f..0000000
--- a/docs/img/sequence-puzzle-module-init.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="217px" height="151px" viewBox="-0.5 -0.5 217 151"><defs/><g><rect x="20" y="0" width="40" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 40 20 L 40 150" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 38px; height: 1px; padding-top: 10px; margin-left: 21px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Main</div></div></div></foreignObject><image x="21" y="3.5" width="38" height="17" xlink:href="data:image/png;base64,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"/></switch></g><rect x="35" y="50" width="10" height="100" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 139.5 70 L 120 70 L 51.37 70" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 46.12 70 L 53.12 66.5 L 51.37 70 L 53.12 73.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 70px; margin-left: 92px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">update</div></div></div></foreignObject><image x="75" y="64" width="34" height="18.5" xlink:href="data:image/png;base64,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"/></switch></g><rect x="130" y="0" width="20" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 140 20 L 140 150" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 18px; height: 1px; padding-top: 10px; margin-left: 131px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">A</div></div></div></foreignObject><image x="131" y="3.5" width="18" height="17" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABECAYAAAAiL3M8AAAAAXNSR0IArs4c6QAAA35JREFUeF7tmk3ITUEYx39vQpJENmxkYSHFjmKjUDa+SSgpiiKSUpQk5atQsqAo+Vz4tlGirBQlWUhWsmFhIcnCQsxT59U0Pfeec8+cmXkXz6l3896ZufP8zn/+859z7hB29SUwZHz6EzBANQoxQAYozkRMQaYgU1AcAVNQHL+R4EFTgWvAEq+UD8B69/c+rrz43iMB0BrgnlLKfuAc8De+zPYjlAY0FjgN7FFKeAZsAb62Ly++Z2lAs4E7wKyqFIEhS274Wgvcjy+z/QilAe0ALnpwjgOHPEhXgd3Ar/YlxvUsCWgScAVYXZXwAtgLnAKWVf8rbtYlAc0DHnpquQSIMe8Djnn3vahZlwI0yu1OR4DDHoidDpZAWgg8ASZUnxU161KApgE3gUWe/ywH3gBTgOveMpMmxcy6FKAw+9wFtrvl9QOQOckyO+Opq5hZlwA0rgqAsoMNX6HPhP4k2/+wwuK2pQF7lwCkZZ+w+InAZWBdabMuAUiWz1mvcPGbXW4H+xncXD8jyUdFzDo3oDD7SOHiPZKHwitUWhGzzg0o3MLfARuAjwqg8W5HuwBsLWnWOQFp2ec8cAD43cM7NwM3vM/ErFcBrwf02tbNcwKaDtwCFnizrcs3M4DbLjjOL2XWOQGF2eclsAn43Of2jgFOVrlouFlWs84FSPOTE9VR40+N/pc61T0N2tQpr/WSCjvmAhTuSLKlyyn+eYNKtEey2ZJ1LkBh9hlkmWjmns2scwDSsk8D4dQ2kUciR90yrVuitQP1a5AD0GLggff4ImrCXudBVNj6O1MD0pZH68kqHZObdWpAWo55685e31pQGu2UOBeYnDNZpwYUZp8Yc9VeEcWM1+gepQSkZZ9eJ/dGkwVWAI+CxknNOiWgOYA8KZzpFdTr5N4UkJaJ5G2InNm+NB1kkHapAGmPTfud3JvOWRtX+iYz61SAtOxTd3JvCklTZrJknQqQln1WAo+bUujTTvO2ZGadApBkHzHOgwlDnfaLkCRmnQKQln26nnz4Xk3uxSv3ZHIj8KkDlf4fIgWgHE8BeyX0zs26a0CaP8g5bJv7YcL3Lu8sEL47k+E7N+uuAXXMoPxwBqjmHhggAxS3TE1BpiBTUBwBU1AcP/MgU5ApKI6AKSiOn3mQKcgUFEfAFBTHzzzIFGQKiiNgCorjZx5kCjIFxREwBcXx+wf5lq5FzOjpHAAAAABJRU5ErkJggg=="/></switch></g><rect x="135" y="130" width="10" height="20" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 140.02 110 L 170 110 L 170 130 L 151.37 130" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 146.12 130 L 153.12 126.5 L 151.37 130 L 153.12 133.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 120px; margin-left: 152px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">state := reset</div></div></div></foreignObject><image x="152" y="114" width="64" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 45 90 L 90 90 L 133.13 90" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 138.38 90 L 131.38 93.5 L 133.13 90 L 131.38 86.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 90px; margin-left: 92px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">state := reset</div></div></div></foreignObject><image x="60" y="84" width="64" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 0 50 L 200 50" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 47px; margin-left: 198px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">power on</div></div></div></foreignObject><image x="153" y="34.5" width="45" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 135 140 L 120 140 L 51.37 140" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 46.12 140 L 53.12 136.5 L 51.37 140 L 53.12 143.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 140px; margin-left: 90px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">update</div></div></div></foreignObject><image x="73" y="132.625" width="34" height="18.5" xlink:href="data:image/png;base64,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"/></switch></g></g></svg> \ No newline at end of file
diff --git a/docs/img/software-components.puml b/docs/img/software-components.puml
new file mode 100644
index 0000000..3803334
--- /dev/null
+++ b/docs/img/software-components.puml
@@ -0,0 +1,37 @@
+@startuml
+!include style.ipuml
+
+component [arduino-sdk] as "Arduino SDK"
+
+component pbdrv-mod as "Puzzle bus module driver\n(pbdrv-mod)" {
+ component pbdrv as "Puzzle bus driver\n(pbdrv)"
+}
+
+[freertos] as "FreeRTOS"
+[mpack] as "mpack"
+
+[pico-sdk] as "RPI Pico SDK\n(pico-sdk)"
+[i2ctcp] as "i2c over tcp bridge\n(i2ctcp)"
+
+node pbc as "puzzle box client\n(pbc)"
+node main as "main controller software"
+node pm as "puzzle module"
+
+pm ---> [pbdrv-mod]
+pm ----> [freertos]
+pm ----> [arduino-sdk]
+
+main ---> [pbdrv-mod]
+main ----> [freertos]
+main ----> [pico-sdk]
+main ---> [i2ctcp]
+
+pbc ---> [pbdrv]
+pbc ---> [i2ctcp]
+
+[pbdrv] --> [mpack]
+
+[i2ctcp] --> [mpack]
+
+@enduml
+
diff --git a/docs/img/style.ipuml b/docs/img/style.ipuml
new file mode 100644
index 0000000..9ea5170
--- /dev/null
+++ b/docs/img/style.ipuml
@@ -0,0 +1,4 @@
+!theme plain
+skinparam RoundCorner 0
+hide footbox
+
diff --git a/docs/img/system-bus.svg b/docs/img/system-bus.svg
index 440227a..1b04940 100644
--- a/docs/img/system-bus.svg
+++ b/docs/img/system-bus.svg
@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400px" height="241px" viewBox="-0.5 -0.5 400 241" style="background-color: rgb(255, 255, 255);"><defs/><rect fill="#ffffff" width="100%" height="100%" x="0" y="0"/><g><path d="M 78 120 L 398 120" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 120px; margin-left: 70px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Puzzle bus<br />(I²C + power)</div></div></div></foreignObject><image x="0" y="106" width="70" height="32" xlink:href="data:image/png;base64,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+edPfV2jHkS22WabNZFMDMTCjesDikAfQADrY9NNN7X3b1PQ/nFp+NZBlGC4XBwVCG1g8sknN7feeqvdMs4rVRLMm2++abbeemvz3HPP2dfS+RNOOKGHJiLJkLqQEVrRIossktfl4O+SoV2lEIilXlDgoSOPPNIceuihjSeefPJJs9hiixVoQasqAtUjwBzB94LrgIJMDh8+3Ew33XSNlwUJRk7YzTff3PphUmJDqiAYOk48zE477WSdyxS0kUsvvTTorb755putGeUX1DX266WvpQjMxM7gt7n99tsbjy233HLmiiuusKTbrqIE0y6k9T1FEXjrrbes+4HNoJAWEySYhx56yKy99toNX0bMARvqTKsE8/vvv5urr77a7L333o1dILaLcSKFfC9yN4o+0Xe0l1AgYFEAaQctyhV8MTiBl1122aJNla7f2wRDICRkTcwSxQ9VYDF455137JihKuNbozBmaI/sQOJgH2OMMUp/P857dvkgekxX/HLOz0ZYw3zzzWd9Y6ygWYvg33//bU39Y489ttGXU045xcY85ZUffvjBygG7qK7gMuBf3iImn2Vr97rrrrMYZRVCNZ544gn7ThZat9OJX5E2MNnXWmst67vM64N7D66ExRdfvPFaNA7GlnlHSMe5555rmP/Egi266KJ2I4Z3TDLJJMGusjkCfvhTKXIB7kEwvIidI7ahKGgOOE+nn376vDGwv7dCMGwXH3744eacc85pvAuhoS8IUajI3SjqEPzDJKiifPjhh4Ygv7nnnttG+eLPAfzUAa2iD51KMEx8dtfOPPPMJse6/GYmEhORlW6UUUZJhsQJ/fHHH293+PIKE41wAhyPMaKBpHxHPW4A/HR5AZx+7IfrBxsgODrHHXfczK69/vrrdrPkvffes/XyYslYNFlQ2Zxw0eZZL8APQnyYb5rE6ocIhqBZzBy0/lDJ+045532FpAfBSCDzwJAdKkswL7/8svWxAIArDD4+l8kmmyyKL8zJzpErM800k2V8CKGvlE4kGASaf6x4qYVASf6lmNpMLLQNf7FJfQ8aLL6B0K6klO9UbUISE31JfVbOiawFEG0QkmQHt0jhW9HG+PasxU8SDOP3xhtvZOIMiW611VbR7khMfZdKD4KRJkFRbaAowaBi33vvvWaHHXZo7NiwmqBFwapZqvVvv/1m6/hCuOqqq1omrsI8KjLAddbtNIJBgIglQrNwBQFfZZVV7KTGfMFccs55H5uUeKIvv/zSrvJsNMgy77zzWjWcs228B4c3ZpMsaL7IsjRDeAbfnr9a85411lgjOoTIqCNUWSkrLou6f/zxh43LgvAoWQugf97Pf48zV9hkGXXUUQ0mK/jK4NCU0H1JMODp2uE9zB8CWXkHpDreeOPlWjASU3+3t4lgpD1FhwEQOze1FCEYBg5blAF3qiACwU4NhyTzzBDpG6CP2IMIMQPRV0qnEYwUfiKdpVlCPBFmDQuAr5VmBWXRrgzudO9iZR42bJgVfikXI0aMsCYYzne/8AwarjxPJrVe8D3ooIOi8hbyv7j3HHPMMeaAAw6IihqHAjfaaCO7aUGJmRshUmXCgy3aA8dn/AK+aP3029d2IHjmYGyXURKMaxMz6fTTTzezzjpr4zWYwMSpTT311JnhKcxjzgmicbrifDtNBCPBwOdAZ6eYYorkuVqEYGSsCaAw+FlHAfyOhOziVKdd8gd1QMVOJRiEGRV7pZVWik5OIj5ZQHxtJGsnzg+PcNCnmFZMBrRt6vqBlqGwAum3y/MxSB+KLxJ5PhwZiU6kOYugT5I4n3EF0HdXwPaSSy6xjtyshZaFGQ3pwgsvbDyLTwa/mCQlKoQIJu88UcoUkCakW+ibCObxxx83Sy21VKO9PPBCL04lGBxetO+r0ahreaeXOSLunHQhgnHMmQJKt9TpVIJJDQXwz7M5zEM7k6EdwazJIsfPP+nrfgvFZnzzzTdW9jDNKXl+O7RsFwbPpoeLC+NZnP7XXnutmXHGGXuIk1zZ0d7uueeeHtoFGwnstrm5kGLq+C/zw/b5e9ZOZ4hgUoNos+aLJGEWEXYWmwhGqo6p23D+i1MIBsbGpmXiFC0+gYTAYrA56dkNJWTiVdVvzAlfZW2l3VA/i4QChFbo0OaB1CyKBHi675OTlb/LRSe0XR2TG1mXfrMIY/a4EvPDSNMqprlJv2cRUnV9kG3EXAWhOZPnR0qRnc8++8xudz/66KO2+lxzzWWuv/76/xFMyJFV1MFLwykEQyAfK4g7JZ3yAa5OHsF0U5RrNxNM3s6CHFNJHsRYsML5Oz1ygSujQYfIIzTZpEqPH4UFTx6FkdoOJjgxUP62c8wsl6t66B3S7xkixJT5Id8Vc29IgnFE4PteUt4n64Sc57hAGhpM6EPLaAMpBFPmA0LPhGJguslE6laCyTMpQmNFjBOrvju3IjcQQjuCZf1pkjxCWRWlpoMfCZNvookmauq+P3GdiTPzzDM3fQsBeDhIxxxzzKZnJWGGdqvkyl9mY4WXSnzR/sgQKc/hSYJJyTiZMl9D48dcbBBMSNjLaAPtJJhu98F0K8E4+zrPX+YLZt5KHdqpyds+jgm+XM1D8SqyP7EJ6cuz07rYovfDI0LamGw/VIf+y77SDzQ3dpCKFN6HSeJC9nk2ZPpIgimjJcb6JX2F7LB1NcFI9ufD87YNiwxap9TtNCdvbMXOwitkuvgmeFULHH1IDaaTGsbll19uTwe7ImNYfL+R/2zIeSt3ZGMHdWPbxlXIXkibl+8rGkib1S8pp/gBGwQTmqydrsGE7D6Ng6lCNJvbyDqLVORtIQF0jug6CYY+hmRZmthSdkL+F3duiTNXxI64LXHpr5Tb0zHTvS8RDMGEZJJ0pYlgQuZGpxNMaFXUSN4iUz6tbrcTTMxnJAlEOkZ9ApJailyQfU1A7pLm5THyDx+mjUharXZrMNI90vUaDDBLh14ZB2TecLEFiEccRyC29FRTTVXo0F5e+3m/d5qJVEatluYG3+xPgDo1mNiZIUkEkkSIDCbpGEX6UKRT0ycnSVxZfo66nK4xmarTROKUuh8s2EQwVQ1wO528IXubv5XZXo8NSCj4q91aUqcRTJnv/+WXX+whPra3XfGduFU6eaXpkxUMJ00ZJztZ/hfXf+mHccdq5PuzdsOkqZXV17yFKOX3Ogkm0wcTik3pdBMJQGV6Cf7GwTVCp2M5LFIGwtV5/vnnbT4Ml5ycv1cR+VikD51GMLEdkaxvkiaF3LUJaThlHfZ+5C19yiJE6Yx12hnzwQ8cC5EEk3XllVfu4YfxiSe2O+Wwev/9922UMKREiUX7FpGXrLrtJJimXaS8bcTUD2y3BkO/ZIIs/kY+DXY78g5MZn0X5MVhMs6PuFImujQVu1i9TiOYMkm35GQMxZ20M9DOYR3bTsbMcbdexCa9JE0cwES/77fffo0ETLH4Gvf+kOYWOq+UJ0PE9Wy55ZbWdOfIDblhyPLIlrpf6iKYGH80dpFCkbxlAp16g2DI/EVSKP80LY41AgXL5oWJ3VJQxv+QJxx5v3cawRTV4kJHQ0JaYOioAGMYymQYw6xMbJQkNkwdbrFweYZiGlsomxu5k5FFl+o176S2zGvLdxVNLh/KHx3rc10EEyJKLKCms0i+U4sPjYVPZ02I3iAY+hO7VUBe5pY3md3voVsFUi6eS22/SL1OJJgiWLz44os2tB5zhBLTAus47JiSkVESG1orfeEkNiVrUZHmEIcWWZgpqZqexIdnU/LmOBkKHRwmnxJyI9OW1EUwuWeR6Kx0OOUdYw9Nkt4imNila+SXYVVBXUy5FymUE9h9J0fq2efPu7qlCHl0Q91YxDG+DdJNhjLH+cLPDZ5+zpKsCRtK14BzmHwjWZnwYukaUsZMrr6QEmkQXIrLLE1emn7+eKamOwmZ4pATcSXsYmWlGSUOB5PMzyyYRf51EYwkaef3atJgJAuV8Wj3FsEwsKw6MHcozWLWzY6omAgUSa3ZRSDRsiykiUBYU9I9dgNpFOlj1pGGQYMG2ejpZZZZpun+bhIi4RvjAjtnLvDOPNM1lnBqtdVWsyfw8S9Iv9rHH39sCQi/m19I64GGIf0Q8ttDCZNcnTynayhA1T1bJOgzpIXQDm1wRes000zT1O2s+9eztJ+6CEY61p3100QwIU9+0aPcvUkwjACMjopLwp1YgeGJl+FCeyYCg+vU99Az2NQIcF5i6CKTtpvqSoIBB1KZcq2LK34qS5duEX+IX1LznFSRMjPrmpsQ9nK72tXJ2zELOTfds0XPUoXMctcWKSIIyAPDrJSkaDw4iUkpGip1EEzIf+u+vUdOXkkQRR29vU0wgJpl5hSZ2Bw4O+mkk+zJ2RTzqkjb3VRXEgyBa+yWIMh+Osysb0pNSu3a4HQwmdrI6la0oO0gtywiqUVuV7vnUpz60knMs6kJwWX/nnnmGZuf2tf6Ur+BgD7GJOsQah0EEzIx3U0kPQhGHmMv6ofpBIJxA0LsCpe1oTpnaShyACEWLlzDLJKqaepg96V6IYJBJea6DrTFPBIocq2GjxsLBZfqESFK5vu8gr8N1Xy99dYrfA9TTBNJWWBDfpgUYop9D+SKgxlzPeXakiJ+xjoIRvpf/IOdPQimSBb0EECdRDCuf3wTl3WRbYsV4osvvmhcEEYdVlfyAONPwDHHf/ujryUm8DGCQbAxMUn1yHYyPizMItR4MuBzGBA/CPlTWolHYvLzDsx1tj7dxWu8Z+DAgdZ04F2YRa1c8CZlN8//4vAK+WGqiCYn2I/8OXfffbe93M5daue+G7OUzIJFvrsOgpERzf7FhEk3O6aweN7qor93LwJZBNO9X6U9rwIBmdFAplINEoyMRyiSf7WKTmsbnYWAEkxnjUcn9UYepZGpVIMEwwf48QipAUOd9OHal+oQUIKpDsu+1JKM0A5FIEcJBvsPR9UNN9xgMYll5OpLgOm3hBFQglHJCCEgN4RC5/+iBEODONXYRcLOyguQ0iH82TwgAAABkElEQVTouwgowfTdsS37ZfL8U+z8VCbByK07kskQTZkVuly2w/pc5yKgBNO5Y9NbPfMve8u6DjiTYOg8Wc/JV0G2ctViems4e/e9SjC9i3+nvV1qL1kXxeUSjGyM6xoIm+/Pka2dNuB190cJpm6Eu6v9ESNGmKFDh9oo7jylI5dg+HQ/3wpH7Yvm6Ogu+LS3EgElGJUJhwCn1jlM6W6DyLufPIlgaBwTaYsttrARlUOGDLGnVMcff3xFvh8goATTDwY58RP93DUpGQaSCSbx/VpNEVAEFIEGAkowKgyKgCJQGwJKMLVBqw0rAoqAEozKgCKgCNSGgBJMbdBqw4qAIqAEozKgCCgCtSEwoLaWtWFFQBHo9wgowfR7EVAAFIH6EFCCqQ9bbVkR6PcIKMH0exFQABSB+hBQgqkPW21ZEej3CCjB9HsRUAAUgfoQUIKpD1ttWRHo9wgowfR7EVAAFIH6EFCCqQ9bbVkR6PcIKMH0exFQABSB+hBQgqkPW21ZEej3CCjB9HsRUAAUgfoQ+C+sE3QomnCHjAAAAABJRU5ErkJggg=="/></switch></g><path d="M 118 86.37 L 118 100 L 118 111.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 118 81.12 L 121.5 88.12 L 118 86.37 L 114.5 88.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 118 116.88 L 114.5 109.88 L 118 111.63 L 121.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="78" y="0" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 79px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Main controller</div></div></div></foreignObject><image x="79" y="26" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 238 153.63 L 238 140 L 238 127.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 238 158.88 L 234.5 151.88 L 238 153.63 L 241.5 151.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 238 122.12 L 241.5 129.12 L 238 127.37 L 234.5 129.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="198" y="160" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 200px; margin-left: 199px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Puzzle module 3<br />(neotrellis)</div></div></div></foreignObject><image x="199" y="179" width="78" height="46" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 358 153.63 L 358 150 L 358 127.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 358 158.88 L 354.5 151.88 L 358 153.63 L 361.5 151.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 358 122.12 L 361.5 129.12 L 358 127.37 L 354.5 129.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="318" y="160" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 200px; margin-left: 319px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Puzzle module 4<br style="border-color: var(--border-color);" />(safe)</div></div></div></foreignObject><image x="319" y="179" width="78" height="46" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAATgAAAC4CAYAAAB3uPAGAAAAAXNSR0IArs4c6QAAIABJREFUeF7tnQXMNUt9xh+kaIDiFiyBAEUu7g7FvbjbxZ3gVqBogru7Q3C7xblQXEuBQLEgxVMIRYJ0f3QmnTt3ztmZPbvnzHm/Z5I3937vOzsz+8zus3+fY8jNCBgBI3BAETjGAb0v35YRMAJGQCY4PwRGwAgcWARMcAd2a31jRsAImOD8DBgBI3BgETDBHdit9Y0ZASNggvMzYASMwIFFwAR3YLfWN2YEjIAJzs+AETACBxYBE9yyW3tJSUduMMX3JH1T0g/COIzFv/+ywZi+9OgInF3S6yUdFv70JUk3lvQNg7XfCJjglt2/TQmutLqPSXq0pA+a6GbbPBPcbFD2NZAJbtn9WILg4oofJ4mf3y57C4fE6Ca4A7rNJrhlN3ZJgmPlD5L0ZEl/WvY2DvzoJrgDusUmuGU3tkRwl5L08cppjy3p74Nt6N6Srpld9xtJN5B0ROV47lZGwAR3QJ8ME9yyG7spwaWrO66k+wa1NP39GyXdSdKvlr2VAz26Ce6Abq8JbtmNnZPgWOkJJT1J0l2TZSPFXa1BKlz2jvdzdBPcfu7b6KpNcKMQbdRhboJjMReR9FZJp01WhmT31I1WemhfbII7oPtvglt2Y5cguJNIelGwvcXVP1/SfST9btnbObCjm+AO6Naa4Jbd2CUI7vhBWsPuFtsrJd1NEupqbCeX9GpJV0l+1+LgqL1+bk/x+4Zg5ptL+kVY99LjM82mBHfMMMa1JF1B0oUlnSys/5OSPi/pbZKIYfRHaNl37iijm+CWBXtbBJeTAndVS1CrEKi9fmkCWnr8TQiO9+f8kh5V8HCXcCUzgiDtN0v6w7KPnkcHARPcss/BtgiupKLWEpQJbpoEh1f7jpIeO8QinqjxMULivt8gdf+s8Tp3b0TABNcIWGP3JQjuFJJ4Qa6arOXxkh4+/Px5Byrq2SRdvxEXuqOCnnf47z2Sa1Gx7zyoe6+V9Nfw+6XHnyLBEZ8IQT2hcN9fGMwC/ybp+5KONTiEzjeopldMVNZ4CSorZoafTMDOl1QiYIKrBGpityUIjpflLZnUcItgb0uXuS0JbiI0upCkN0k6UzLAnJkZLeO32OB4Z24q6XnZHrwzqKrY2/JiCCcO0t4jsmueJekBtstNfYTGrzPBjWO0SY+5Ce6kQ3gI6ugNk0V9Lfz7q9lCeya4U4f7uE6y5ueEl32O3NrW8VsILu/LLTx3IKkHZk6e/LnhXUPqpm8kdWeibPJ2VVxrgqsAaYMucxLcKYO95/BsPeSiPrRgtO6V4ErBynOqa1PGryU43hfCccB8iqrJ9XeQ9ILk+pdJuruLJmzwlq251AS3DK5x1E0Ijr1BtTmrpKtLun2mzjEHdctQl5Di8tYjwZVsV9S8u7Wkj8ywFVPHryU4gqtfMdTmu1JY6xQJLB/jx5IIL/ncDPfvITIETHDLPhJzhzikqy0Z5NO/90ZwJdvV2D207M4m49cSHPv5nsSO9l5JtxwksJ83LBTHw2MGifvByTU4VjA9uM2MgAluZkCz4ZYiuF8G7+Pr1hS97I3gLivp5Qs6FTYZv5bg8HriXIgNuyHe1N83Pka3CljEy0izw8Hyx8Zx3H0EARPcso/I3ASHxIPnkWDR744svSeCO+dAbC8dpJ+LZuSAB3EOp8Km49cQXEnyeveQufDRCY/QuSXh+Y6tlIkyYVhfkiNgglv2mdiU4Iip+tEQJf9ZSZ+Q9JmGski9EFzJozmnU2GO8WsIrpQiN9fTU8pEmWvsQ3ocE9yy27+Jk2HTlfVAcCWPJk4FinRC2pu2ucY3wW26E51eb4JbdmMOZYIreTTndCrMOb4Jbtn3YGejm+CWhf5QJbhV0f5zZSrMPf5UgitlkCz7RHn0JgRMcE1wNXc+VAmu5NGcM1Nh7vFrCO54IcA3rab8EEnkAbt1ioAJbtmN2SXBlQpjttSDI8CYMJQLJhDVXF/yaM7pVFhi/BqCAwZi1ziqMTYXGl32/dl4dBPcxhCuHWCXBFfy+iH51IY1XCyc1pWWAhojuJJHc122RSv6S41fS3DXDoUr47o/FTJJvtNwIzHdi3xiQn2+MuSoUhSTTI60GkzDkO66CgET3LLPRm8ER0oUqUY1jZzLp2Qd1xHcqgNx8vJHNXOX+iw5fi3BnSWUckrj+agJRwn5WN5p7P5OH8pdXT7p6DM1xlCb+HcT3ETgKi/bJcGVAlOfESp2jFWTLb2E3PIqgltVH20up8LS49cSHEUuKXBJ9kIqxd12RT5w/piwJ5AZJ6PFRtjMdYefL1Y+U+7WgIAJrgGsCV13SXAsl7MNXpW9TGOJ7aikTxwKMd6lcL8lglvl0ZzLqbD0+NxmLcHRt1Rn7l3hTAzIalXjPpDaXpKlq62qBjPhcfMlOQImuGWfiV0TXKl2GTax+0v6QJbHysEpFxhUrUeuOV+gRHAlj+acToWlx28luJIUxhjgStmq9xdKV6Feo8o+LKvsiw2vVvpb9kk9oKOb4Jbd2F0THC8j+Z6p5y9VrXgZCb4l64ESQBygEhskRenttCx3TnBnDDY9SCi2b4dqGZw3gMeTNbQ2yn1zMMtpFh4/Jre3SHDcS8keGO8RKe7Dicp6riHF7hqFkuX0u3c447YVH/evRMAEVwnUxG67JjiWTaFM1CDK+tS2qHJBaKmKmxNcSUKsnWNdvxh+AYG+fijRftgcgyZj5OEdrQQXSY44OH5aG+SGLY7S87XOidY53N+nai3+DPRAcPFlLKlIOQBIc9jOMIJTkim34ZngjooYaj3noHLWwqUrnya82JgBxqrBVA7nbusQsAS37PPRC8HFuzxV8NihMiEVcTYAREaVkg9KesNgE0K6iFKFCa7u+cDLizqON5T4QdTSeO4CZ6FScfmIwUHBwTQ/sNRWB+ocvUxwc6DoMYyAEegSARNcl9viRRkBIzAHAia4OVD0GEbACHSJgAmuy23xooyAEZgDARPcHCh6DCNgBLpEwATX5bZ4UUbACMyBgAluDhQ9hhEwAl0iYILrclu8KCNgBOZAwAQ3B4oewwgYgS4RMMF1uS1elBEwAnMgYIKbA0WPYQSMQJcImOC63BYvyggYgTkQMMHNgaLHMAJGoEsETHBdbosXZQSMwBwImODmQNFjGAEj0CUCJrgut8WLMgJGYA4ETHBzoOgxjIAR6BIBE1yX2+JFGQEjMAcCJrg5UPQYRsAIdImACa7LbfGijIARmAMBE9wcKHoMI2AEukTABNfltuzFojgs+tXD4dBXCavlZPcbS+IUqV22h0t6dLIAjvR7zC4XtMW5OSj7ReGgaaY9lO69CLMJbotP3wGbygTX14ZydOGjsoOoTXB97ZFXs0cImOD62qwrS3qTpBMdotKrJbi+nse9X40Jrp8tPLOkV0nioPG0WYLrZ4+8kj1DwATXx4YdV9JjJd2vsBwTXB975FXsIQImuD427SaSXpCppnFlJrg+9sir2EMETHC737SzSXqlpIuuWIoJbvd75BXsKQImuN1u3AklPUnSXcMyPiXp45LuayfD/yPgMJHdPqT7PLsJbne7x3t7U0nPC6rpbyTdeYj/O2aQ6KyiBgQORYK7efA4xYfgUuHLx78x2F5G0s0kXVzS2UOnT0p6v6TXS/qPIYDyL4Vn+8SSri7pekFlOJOkXw5Bl5+R9E5Jbxi+tj+d+E4Q43R+SdeWdFlJ50tsLqzt88Pf3xbu47cT5+CydJ4rSbpYGOsLkt4l6TWSvi7pr5JaCA4cwe6wMF5rUHDL9ZsG+h4/7B/7eJEEg7iXSElvWfMcbAB/9aXnlPTSRDV9jqQHSLpu9mxbRa2G9OB0LBHcJwKhPW14kS88cqs8TLxEPPA0vprXH8jhXxJCLA1Bf9QHov//VAknhHtNSQ+sWBdDfk/S04PRuYXo+NBBoASKMt+qhqTwTElPkHSchkyGFoIqzd1y/VSCA+t/CtH/8cO2bpv4aD1SEuQP4W+roZo+VdLhYUJU09sOWSRfk5Q/2ya4be1KR/OUCO4Mkp4t6WSV64xfzD9Iuk8gvDTAch1BPCTMNfZSsBZSjKKNpXJpf+uGhMG6ILyxhtQGJk9puP/nBvsPKlJNqlYLQe2C4Ehxwp51yzGwsr9D+OwnONR+tBqnOEp3PkTsFY4FWlRNXxtI1gSXoWsV9f8kLx5sVEoakhbq2FeDlHKJEECZExjXoKpGOwjXkof5dkm/CCocKmUuDfClvWEYf9XDfmpJzx+kg+sUOiAxoC4zB2tCxUZtzRuq1O1HckNzW046Rn4vqKxIebFBcueWdOnwi3VqZ88EtwpryOPTkjAB8P/rsH7Q8Pcnb4HkzivpdYO6j4pKix/aKK2b4ExwRxPjIyQ8xCRpE1P06wQnSOBCQTVL3fHY07DX8ODzct9/eNk/kNnnUHtuEVSKlCAJykTNKElxjIk0cfdsr5DKUDkg3vw6ItlRL29VuOZOkn62gknzFyaSNOt7X/bCoopfIASVkhaUt30kuNwTyT3xHEAcqPo/LrwvZwnmCIz86bNzx0A+K6De+NfYeDEPxD1OVdM4uAnOBFckuFzULz2N2NneXPhD6UFLu6EC8oVPK1qQM3iHQY3878J4SG2oICkhPm6QJvlZZ1djHjxp9Euvvfegej6jQIqlCHjuhXX9+5rXcZXEs48ElxMCzwEmAZwpJUdShIWPEEb9f05w+lDQBH64MZUdfQA+sveUhI04knCJUE1wJrgiwUEAPLDY1Fa10wWj+uWyLzeqKh7Mde2Ckt4xqJ2nDZ1wauCpzW1kSBTPknSbZLBXDOroPTKpctVcpYoSqKpIkd/NLjqXpDcm6g4v9w0kHVHxgqIiYfeJXlEu2TeCO6mkFwevd7zlFlUzl6gYg48DY87d0CD4KEYzCs8Iz+vvsolMcCa4oxEcLzYhAaiX6xpfbdRKVL7Y3hu+2j8fuZYHE6kAe946MsiJEBUJ1z+2oNqGCgX5pOo0BIf3Nm3cB/bD2F4W1OIa7ysSBU4M7E6x7RvBXTE4Y6K0O0UCy8dYJ5nX7l/e75TBHsszSkPK5qP6zcKAJrgMFDsZpFXSVP78HCuomQ9O/vD44EH988jTWxszlpMOqurdgl2o9gUprRNiRjr5YxikRNaotzg2ahv2O15o0oVo+0RwPPcPzcwGhJeQtD7m3U7xyaV6SAcp+Mu1II70Yy8JLcImS+NjvM7WZ4IzwR1NgmshkTzGiocP8hhrNQR3vCARpWEhtePn8+O9TdVmHAY8/HheafmLiaR4reHnc2M3kvwdFQ/srrGHBIfURlhQGhZC0jrByC3tBMEZgWoaGzZUPOlzNLzjL69QTeNcJjgT3NEIDqkFdSu3Z5Qe0JzgSqpf6boagjtJKDeNBLDpyzImXZ0jZFacJ0wEsfGCf6vhrcwJeZ8kuJI9FbvWDxrun65/N4SRXDWrw9YqCa+aMnfmrFNNTXArULSKKtWqmUC4JMHlJMh8aRpZy7s3FndGYcQjkwFzCa92rhSPfSK4HJ/a+63pN0f2AM4iQnXIGKGhmtY4syzBWYLbKJ1lXwkuJ0sT3FFzY2uIq7bPHAR3hZBTGr3uOHOwGa7z8rM+E5wJbqOHYF8JLjd+m+D6Jbj8ZKxVYT4lwjXBmeAOSYLL1UcT3GbVTWqluSn98r2ZMsa6a6aaPeZex1bGsw2u7ezIJSW4OZ0MeTxd7kQYs9HVPHx5OMo+2eDOGtKqwCnauEg/I+90180EN+MOmOD6ITjKD2FUxqMbG5UqcIK0Ng5gJik7NooHYKT+VfgFwaMEHpNAH1/wqyV18Wrmy0Mt1hFcbaDzqnmpS0eGRQzKXTdXTbmkPMSFeWs94jXYbNLHBLcJetm1Jrh+CI6t2Vag7xwxdy1SYO4h/spQMPJGoXhmzeOcE/amBFf6mNSk6+VrhSgJMzpFqMdGmA0peS3hNvmYSJXkE09pfLjSii9UhMnTAflotsQ7TllHN9eY4PoiuFKqFvFpH214YkohECXpJDdIE5xKEcXaqsOUYnpRsq51pFMKgSGItea+SmS0KcGx7Lx4AmWswLolCyE/bHlKwHTD1o52tZPBEly3Tga2ZolkewJEKe3znWzvSzmrpAFBWmPpSqcPWQyXryS4UubAupJR6VJLJZ3mILjSYcl5fbV1jJLniNKXTAgwTMttjbLSjB1McCa4rgmO7SmVS6I2GXFQU8olUXWCar15vmxegoe5UWfuMpxDQBGBVSQHWT0x9Esfp3WkU8r9HCszxdgQKSlVeeHPOQiudP/MSQkkcj/XZbZQaoo0ulSVrA3GnZHPjjaUCc4E1z3BrSp4ue4MgDMGAkR6SBv5qNj1frLirSrVdqOiMVWOKfyZEiqEgPcRcouVLWoJjn4Yz9+T1arDcUDxgvxcAyL5kQ5Jfi+dkTEHwbGmkhTG76nGQv2+eMBOep+riou2SH9LkZwJzgTXPcGxRXOULK+RkJgrP6EpPiJIcx8OxvN15bpj/7GTskoVTOK1lKr6SKh2AllThigt9Q55/D4583Muglt3//wtLQ+PLRC7IWvLG0SN5PvtpZirclwTnAluLwguSheEjdyu8uFOuyHtoUKVaoaVhsO5gSq46oT00jWozai98aDhMYJjDEorkdReKnm+6jZfGEo9UTaKkvK0OQlu6rrieiE3ysvXYj1hO6svMcGZ4PaG4NgqbD14+1DjYuWPdU87YQHEzXEGa011lHQs1DUM/5RrWndCGCos+ZY4I7Dv1ZDO1HlQlSnKyb3UJvbXxMGVMMTBg4p/r6Q80TqsV6ny1Wy0QEcTnAlurwgublc8jBjJh1SbePAzhu0vhsogSBKopa3Elj4S2NkIyiVGjYRv7F8cX8jLTGFQYrzemoSS1JJO/i6vmge1GOmMwOR0Hq6vnWsqwcU1QnTYC3Fs8FHJD9nGLkehz4/t0Fu6ihtNcCa4Bb6bHtIIGIEuETgUA3273AgvyggYgfkRMMHNj6lHNAJGoBMETHCdbISXYQSMwPwImODmx9QjGgEj0AkCJrhONsLLMAJGYH4ETHDzY+oRjYAR6AQBE1wnG+FlGAEjMD8CJrj5MfWIRsAIdIKACa6TjfAyjIARmB8BE9z8mHpEI2AEOkHABNfJRngZRsAIzI+ACW5+TD2iETACnSBggutkI7wMI2AE5kfABDc/ph7RCBiBThAwwXWyEV6GETAC8yNggpsfU49oBIxAJwiY4DrZCC/DCBiB+REwwc2PqUc0AkagEwRMcJ1shJdhBIzA/AiY4ObH1CMaASPQCQImuE42wsswAkZgfgRMcPNj6hGNgBHoBAETXCcb4WUYASMwPwImuPkx9YhGwAh0goAJrpONGFnGZSW9PJw6/2RJD5X0h/1Y+kar5Pk8h6SbSbqSpIuF0X4j6YuS/lPS4yR9c6NZ2i6+iaQXSDqRpAcN/2U//tQ2hHtvCwET3LaQnj7PqSU9X9J1JH1NEi/Yl6cPtzdXHl/S/SQ9IJBJaeGfC3h8a4t3dWJJz5R0K0nfk3RrSR/Z4vyeqgEBE1wDWDvoeuwgJTwmzP0QSU+S9OcdrGWbU/Jc3lPS00Ymfdcgxd1S0q+2uThJlxkky9cNH57TSmINd5D0X1teg6erQMAEVwHSDrtcQdKrwov0cUm3kPTdHa5nW1OfSdJrJF0imxCJCXX0L5KQ8L4k6f7DR+D321pYmOe4kh4bJEx+9XBJT7CquuVdqJjOBFcB0o66nDKoptcL899R0osk/XVH69nmtJccbG5HJhNic7tPIPtebI/nDVLcOYOqenNJfITcOkLABNfRZiRLYV9QezBm094fbD4/7nO5s68KskByje2Vku42SEwQXS8N88GjJGE2oL1C0j0k/bqXBXodkgmuz6fgzOEFR5KhQXYv7nOpi6wqJziIhJ/epNdzSXqjJKQ4yBd74NsWQcSDTkLABDcJtkUvyg3sn5J008Fb951FZ+1r8JzgHiEpOlp6Wim2OJw+OERokN2dduD06AmTrtZigutqO/62mFx648VGejnontN0J/aF4FjzFSW9JYSyWIrr7H0ywXW2IZJuH5wJrAyb23UlfbphmccMJHntIT7r8sPLd1gIEGaIb4RYOuK23hf+jUdySjtp8HIShHyhMM/JkoE+OcSofT3M80FJP10zydkHNe/1YYzateBRfvVIZ2LWLi3pBmHs84f+eGPxwH5I0luDk2Cq+nsKSdgIrxrGfpmkuw/e3d/W3oj7LYeACW45bKeMDGlga4ueUyQDCK82zut8QwgF6ly8fmwN7xzsWo8cgoi/0GDfQsIkAJcAV6L5axqSzXNC1P/PChfMTXAnlITX+WGSUtJdtVYcBOAwJQSHd4jMkqhCT/ko1WDoPhMQMMFNAG3BS3AqvCchDuKriLcaky7YR6S1lyTSWu0yYwgGqWDrUo6YA+J8yoQ54loIo4CwkSTTNifBkdr1dElXrgUgkeruG9TNMbzzofN9OxTNCo1wb6e7CW47ONfMcqwgRUBqsfGS/mvFxXjxXjqQ40WzvqiJHxvCF34Rfn/GYDOCUNKG1IHKhyq5qqX5sGkfyAoJ8CvBTsh9oBazFgJ280baGTFtv0v+cJqQcoXRnnbusJ7Y5d2SPpoNhJrN/aVtFQ6/HAjvE0HV/+OQanXykNsaVdY4BmR/Z0mvrfiopPOeLqjLlwu/PNTCeioe0d10McHtBvfSrLktpzbP8jhBPSJnMzbShyARcjRzaYT4rasEdTElunW2o1NJeqEk7HqxYcNiTkixJPlBVleX9PiBMNJ5alS4KU6GNGc3rhFi+5eg9ufxadgqLxAk5FTawz7XGrRLVsVTgweVuSHKqznwd/cvlwlu93sQV3BBSe8IaVn8rja4NU9rqg0rSdPAmA/iudbwA7Hm7fqS3pz8siXpHxIhaBfpKjakJCS5Va2V4JAaIVsqi8QGUd0uOBLWqZzY6EizOjy5dkrQLh8U1PfYUHchPbcdImCC2yH42dRUp8AOFhuSD+rqWHgIJYSOSOx2JRWwdJd5DBd9SsSDhAgB8ALHhpOBl7fGVgX5YJN6cHL9WOBuK8GdJaiVUUVvVTVPHz4o2DFpXI+98QMNj8c/hn2Il5BWd6+BeP+nYQx3nRkBE9zMgE4crkQCeCmRJMZanrdZK/kxLqR6l+A9xIaGXSvPp4QIrxHUOby02K8IZm0p2ZQT1hgJtxJcGlrDfU2RwPIxIHDqvWGzq2nkpr5psMWdLXTGDkcdu5LXuGY895kBARPcDCDOMMQJguePlKzYah0MeA3fMKiQ50mkD6StMa/oDMuuHmJJgsvtXyyqJkYuX3xOUB8OtrgfVd5l7mjgg3GjEAtYOYS7zY2ACW5uRKeNh1RE0CrGfxoqEgSXewlLoxPz9axBCrtN9kdi3PAG4gT4SaU6OW3141ctSXA5sbRgl66c6i2UaKJyMG2dTbJ0x8QwIj0j7cZ2KTsaxh+OJXuY4JZEt37sPA4MD+WNC/Fiq0aEDFGPVgXeEsaBZ/W9odT3NqLsTxLCPYjwv2HmSZ1TRc0lL4gJosGD2tKQBJG4UmdIrRTNPCVJkurLZGi47QgBE9yOgM+m3ZTgCP1ALcUpMZZdgISD8ZzEcOxE61KoxtDBAYHkctYhU4FQEuLXYtpWKQYujjcnweU2yLE1t/y9RdWdS1VuWZ/7jiBgguvjEcmlkFYJjrsgrovQD0IlLtxwW6SDEd5AIGxNXipEhqRDfifBv1PaQSS4kre5hSCn4OhrTHB78QzkUsgUgos3ijRHuAReQQ6qqcnFRKqj7A8nRKUZBil4rfmd8VoyHTDUxxAMfn8QCY77QoJ+dAKaCW7Hr58luB1vQJh+DgmudCdIFXhXKelDVsGYxEWwLNJcHnuHAR7yo6DjuoatD0L7bAgYxpOILYxwibRC75IER5UUnBoxPW1bO3y8gNFdTXDbgnx8HhPcOEbb6LGpDa52jRj+yb8kM4G0q9xOVsqCyE/2inNBXpAWOaIcBEPFk1Uq7pJe1DzQuTbFrRaz2n62wdUitcV+Jrgtgr1mKoz0HENHuhZtExW19o5QOTmRijJBacs9f2lZ7tiPc0EpEVR7RsKSBJdjt6s8UHtRa5+8LfYzwW0R7DVT5XFwdK2JoSLL4CLhB+8lVTlID6rNMkCie3ZQ6eLy8vLgZC08L1k7RSJRVX9YCR3PGCSaEumcKir3QFoUTo/YWlLJ4jWke1FuisIBqNrUhiP/lhjCmjZ1D2vGdp+JCJjgJgI382WlTAYcBG8fmWcOtSg3jKcEV0oha01hyot4cktzEhzPMCEy2Ahjm0LC6SlmjINXGdshSfs1LS96sA0pvGZdh3QfE1wf21+ScsYqbsSV5xJWSx5miSDTHNhS6AOVeZGQag5bzo8/jGuek+AYE+mVQOfUpkgeKaS3rohnXA/5owQHp/X08CpD/s5F7eMdmbQKE9wk2Ba5iMwF7HCx1UpKJRtZ7cudl0zCWYCql6q4VAFJyxAhmXDKFyWT1jXi8rDnYa/LQ1XGKm20JtvnJ82zrtpKxQRGPzEUHYj3g9QGDniDaxtOm/TIwJYPQe0c7teIgAmuEbAFu+ehIqRWYesaO48hP4A4vty8YJTuLh0WDSGQPkUxyFTqQeLBeZCeHp+eGhVvn/JMEF/pLAeI7R+CA4NqJaU2FsrRSnDMUZLC+D0fiqcNteG+ny2EZx+PMqWbrpn9rfYDkV6WfwhqJfAFHykPbYLr5xnIjeUlaWrVavOjBmM/pBhO5CJpn/9fV06cEJHbFiQzTqZCCiuRVV4SncomF8/yTlkLObAQaczzHCslNIXgmGdVWXX+RimoIwMOSG0k1ecl3ulHFRZU8JY4utyG2pqo389TeMBWYoLrZ0Pz05lYWY2jId4BISZ4REsv7dhdUgOOw4s/v6IjcXqc9kXGRUsjyBenBd5I1NJYaWOslNBUgmNtEOxzG48gjPeEHQ5ya63hljsYWk9Da8HUfRsQMMGtmW8gAAACt0lEQVQ1gLWFroR8cE7nacNctXa4uDTCREgVwvY1lnTPNRAQISCocGMv9RmCSrtK7UzhQVpEEkLlJdyiNU9zE4JjHWRe3DtUKK5JVSP7Atwg4lQ9r93y3P42JUyldi73a0DABNcA1ha65mpqa9HFuEQS4nEgUF8OtZFo/9jigcycVIWqOGbjS2872tco5400R1J/JBDscTggsK+VDnrOz3VY5+3dlODimglRQRUlTS3FAQL+YrAhIm2hnq/KwR3b9jyUBucL9s2vjl3ovy+PgAlueYxbZ8hLZ7eoqa1zuf/mCOQFN58RDsCZIgluvhqPcBQETHD9PRCop0g3sbKsX5j+9ihdUSqZTjmspu+72/PVmeD620D2BIM/djGaVZ7+9iiuKC8X3xJk3e9dHaCVmeD63Mw87MNG6z73KXUKIb0RHEyMoFsnCJjgOtmIbBl5ilNrbmWfd3WwVpUHWFt663B/TXAdbkpYEp7QF4a6bfzqjiGWrOaw5X7v6uCsjMwTUusIXia1C89vfqbswbnbPb0TE1zfG5eelmUprp+9yqU3cnUpB1WT2N/PXRwCKzHB9b3J+YtE8CpeVUtxu923tHqJPzy73Yu1s5vgOt6csLTTh1I+HNriGmO73y88p2SYHB4KGXCwDIHNbh0iYILrcFMKS0qTyEsVP/bjLg7GKgm8JmeVVLgpVUcOBgp7chcmuD3ZKC/TCBiBdgRMcO2Y+QojYAT2BAET3J5slJdpBIxAOwImuHbMfIURMAJ7goAJbk82yss0AkagHQETXDtmvsIIGIE9QcAEtycb5WUaASPQjoAJrh0zX2EEjMCeIGCC25ON8jKNgBFoR8AE146ZrzACRmBPEDDB7clGeZlGwAi0I2CCa8fMVxgBI7AnCJjg9mSjvEwjYATaETDBtWPmK4yAEdgTBP4X39VRQJX3b2MAAAAASUVORK5CYII="/></switch></g><path d="M 238 86.37 L 238 100 L 238 111.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 238 81.12 L 241.5 88.12 L 238 86.37 L 234.5 88.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 238 116.88 L 234.5 109.88 L 238 111.63 L 241.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="198" y="0" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 199px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Puzzle module 1<br />(software)</div></div></div></foreignObject><image x="199" y="19" width="78" height="46" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 358 86.37 L 358 100 L 358 111.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 358 81.12 L 361.5 88.12 L 358 86.37 L 354.5 88.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 358 116.88 L 354.5 109.88 L 358 111.63 L 361.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="318" y="0" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 319px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Puzzle module 2<br style="border-color: var(--border-color);" />(hardware)</div></div></div></foreignObject><image x="319" y="19" width="78" height="46" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 118 160 L 118 127.37" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 118 122.12 L 121.5 129.12 L 118 127.37 L 114.5 129.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="78" y="160" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 200px; margin-left: 79px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Power supply<br />(battery pack)</div></div></div></foreignObject><image x="79" y="186" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="400px" height="241px" viewBox="-0.5 -0.5 400 241"><defs/><g><g><path d="M 78 120 L 398 120" fill="none" stroke="rgb(0, 0, 0)" stroke-width="4" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 120px; margin-left: 70px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">puzzle bus<br />(I²C + power)</div></div></div></foreignObject><image x="0" y="106" width="70" height="32" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARgAAACACAYAAADQzHYWAAAAAXNSR0IArs4c6QAAIABJREFUeF7tnQe0LEXRx/sJioioRIlKUkkKggQFJIgECSLyyCogWXJQCRKEB0pGEIkiWUSCIhkUJEcBJaogSSUKCGKC5/nNd2q/mro9Mz17d3b33qk6h3N4d2d6emqq/125J0yePHlycHIOOAecAw1wYIIDTANc9SGdA86BjAMOMC4IzgHnQGMccIBpjLU+sHPAOeAA4zLgHHAONMYBB5jGWOsDOwecAw4wLgPOAedAYxxwgGmMtT6wc8A54ADjMuAccA40xgEHmMZY6wPHOLDvvvuGSZMmdX5aY401wi9+8Ysxyaxll1023HzzzZ25H3744WGPPfYYk+/S1KQdYJrirI8b5YADTLsEwwGmXd974G/rADPwT9DXCTjA9JXd/jAHmHbJgANMu773wN/WAWbgn6CvE3CA6Su7/WEOMO2SAQeYdn3vgb+tA8zAP0FfJ+AA01d2+8McYNolAw4w7freA39bB5iBf4K+TmBcA8zcc88d/vSnP3UYevvtt4cll1wy+/e///3vcN5554Wf//zn4d577w1//etfw3/+858w00wzhTnmmCOsssoqYYMNNggLL7xw5QfhGTxL01NPPZWNk0I8e9ZZZ81d+vjjj4e55pprxO0TJkxIGbLymtNPPz1sttlmfR9/tAADXy699NJwzTXXhN///vfh+eefD3//+9/D9NNPH2acccbwsY99LKy66qphzTXXDDPMMEMlH0ZzgU20O+KII8Luu++eDYksXXjhheHiiy8Ov/nNb8IzzzyTk6/PfvazmXx99KMfrZxCP+VLT+bNN98MN9xwQ7ZG7rvvvvCHP/whvPLKK+Ef//hHeOc73xne9773hfnmmy8suuiigYTJz3zmM+Ftb3tb7n3GNcAgbL/97W87L3zVVVdlwAHQbLTRRgFhLSOYte2224bDDjssTDPNNIWX9lMA2gowf/7zn8N+++0XfvSjHwUEv4qmnXbasOeee2aZtVNPPXXV5V39bgHm6KOPDrvssksmX1/60pcyAKySr2222SaTr3e/+91DIV8yicsuuyzsuuuule+gJ/2Rj3wkHHnkkRnYCI1rgFliiSXCXXfd1XnZn/zkJ+EDH/hAhrSvv/56slCttNJKAYaD2jFygBnJlSINqRsN5p577gmf+9znwrPPPpv8zeTCpZdeOlx++eVhuummq31v1Q0WYI4//vjw8Y9/PKCdsMunEvLFHKeaaqqByxcTACh322231OnnNZYJEwKanNw/rgHmk5/8ZLjttts6DEAAqBd54oknsr8BQOuss06m5qGh/OUvfwloOZdcckn473//m2Pc1772tcD9gwaYK6+8staHZ7ffcsstMxNQ6O1vf3u48847wyKLLDJirKbHrwswaKCf+tSnwmuvvZab6+qrrx7WX3/9sMACCwS0lZdeeinbTM4555zcpsJNLHrk4B3veEct3lVdbAHmqKOOynZwzCHoE5/4RFh77bXDPPPMk2koaGGYdph4Vr522GGHcNxxxw1cvm699dbAe7311luduWAKbbjhhtl3YINmo/3nP/+ZrSNqsc4///zMdBJCy77uuuvCiiuuOL578sIQGCb0wQ9+MGMKYPLDH/4wE9AYsfiw4Z977rnOz1NMMUVmhy600EIjbumnBlMl9Pb3b33rW+Hggw/O/Vn7CuqON9rx6wAMfjI2gfvvv7/z2Pe85z0BTRQ/SxGdeOKJYccdd8wt4v333z8ccMABo33d3P0WYPDDYXYDeMjXeuutVyhfa621Vk4jm3LKKcMDDzwQPvzhDw9UvjBv0KaE0AApRi3zZ/3tb38LG2+8cdCbE/ex9sa1BmMFAKaBrjBwtdVWKxW2X//612H55ZfPXVO0ywwrwFx//fWZOah3I96b9++FL6eb8esAjFXVAXmeyXetIrQJcbhyLdoLm8sss8xSdWvy70XyhRaMmVRGN910U1huueVyl+y0007h2GOPHRjA4JhG0wLYhdAgUwIdmIT4YJ5++unOvayL1gEMWgsqXQqhhmtUJtKD+msX5zACzIsvvpiZQKKu877vf//7M21g5plnTnn90mu6HT8VYDiui92cyIVQ0QKMTZT7MZ8eeeSRzs84U3H89opiAIMpQXQyhfArXXHFFZ1L55xzzvDkk08ODGAAB+YghFYF6KTSWWedlQVViH7yHxZE6wAGzcTuHEUMxFG5xRZb5H7+3e9+N8JMGkaA+fznP5+FF4UAxZSdNVWYuh0/FWBuvPHG8OlPfzo3naLQfdGcjznmmCwSIkRIWJtbqe9adF0MYJh3iobFmETENt9889zwDz30UJh//vlzf+uXfMXSJfBLjkbraxXAEEkg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rrvuumGWWWbJjnXloPqTTjqp8+xjjjkm7LzzzpWf7LjjjsuO5HzjjTcqr025YNFFF81OgeTUQCfnQJs5gMXBiaMoHkIc57v55ptH2VIKMHvvvXfu0PD1118/nH/++aX8TQUYbDpULCaMw/jKK6/Mjp60xDPFHFtsscVKD39HU9lpp53C97///egcORJ21VVXzTSymWeeOfvvzTffDC+99FJ48MEHs6Ner7rqqoBmZQnQ++UvfxkWWGCBNsuXv7tzINx7771h8cUX71gGaPq4IvBjWioEGDQIFpMsNkyEhx56qPKs5lSAOfXUU8NWW22VzWeppZYKt912W/TTYeJ84QtfyH6beuqpA1pVEWEScTysJc6D5hB0wKWKcASjKXG9BZo555wz3H///QGGOjkH2swBzlY/88wzOyzYdtttww9+8IN0gNlwww1z2grAcfTRR1fyNBVgQDz8JBALd6GFFoqODfDIIfAcrM2h9THChNlggw1G/LTnnntmTmS0pDpEtAn/kMxR7uUZHGreT+IAcnkmIcIzzjijn4/3ZzkHRnDgqaeeylwGhLAh5JLNd8EFF8xdG9VgHnvssexmcY5y8+OPP54BQRWlAkzVOPI7qLj99ttn/8QXgtfaEmFtQsw2WkX0C62mW3rmmWfC0ksvHZ5++uncELfeemv2934RACkpAXwLzEon58CgObDFFluE008/vTMN/DD4YzRFAWaHHXbI+THKwtL2JXsJMJgomDdoOxDmzx577DGCr/vuu2+YNGlS7u915lz2oa6//vqw4oordi6ZaqqpMmf0Pvvs07fvO2iAeeKJJ8Jcc83VeV9rqr7wwguZYBENxIx+8cUXM42RFIX55psvS8ZEI+bf3RAAjxZ33XXXZXlMjI8pO80004QZZpghzDHHHFlqwcorrxyWW265wkfgb5tppply6RDkcuCTqyJypoicanBfYYUVwq9+9auqW7PfDz300IBPU2jTTTcNZ511Vum9hIWJnOL7gwfPP/98psHzDvgP0ewx+1dZZZWAXKYQfFxrrbU6l6Kl44aA4Cn5bVzz5JNPZu4I/bsdH18MQSAh3CjICv5KoREAQ+SFyb/22mudi3hBvcjKXqRXADN58uSAnScfAQFHuMiL0QQIoVkh5EIIHZGvsvh8yseQa1gchOkJybFYiHj1kwYNMDjB4akmVGMECmDBsf76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"/></switch></g></g><g><path d="M 118 86.37 L 118 100 L 118 111.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 118 81.12 L 121.5 88.12 L 118 86.37 L 114.5 88.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 118 116.88 L 114.5 109.88 L 118 111.63 L 121.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><rect x="78" y="0" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 79px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">main controller</div></div></div></foreignObject><image x="79" y="26" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 238 153.63 L 238 140 L 238 127.89" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 238 158.88 L 234.5 151.88 L 238 153.63 L 241.5 151.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 238 122.64 L 241.5 129.64 L 238 127.89 L 234.5 129.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><rect x="198" y="160" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 200px; margin-left: 199px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">neotrellis puzzle module</div></div></div></foreignObject><image x="199" y="186" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 358 153.63 L 358 150 L 358 127.89" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 358 158.88 L 354.5 151.88 L 358 153.63 L 361.5 151.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 358 122.64 L 361.5 129.64 L 358 127.89 L 354.5 129.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><rect x="318" y="160" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 200px; margin-left: 319px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">vault puzzle module</div></div></div></foreignObject><image x="319" y="186" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 238 86.37 L 238 100 L 238 111.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 238 81.12 L 241.5 88.12 L 238 86.37 L 234.5 88.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 238 116.88 L 234.5 109.88 L 238 111.63 L 241.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><rect x="198" y="0" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 199px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">software puzzle module</div></div></div></foreignObject><image x="199" y="26" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 358 86.37 L 358 100 L 358 111.63" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 358 81.12 L 361.5 88.12 L 358 86.37 L 354.5 88.12 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><path d="M 358 116.88 L 354.5 109.88 L 358 111.63 L 361.5 109.88 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><rect x="318" y="0" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 40px; margin-left: 319px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">hardware puzzle module</div></div></div></foreignObject><image x="319" y="26" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 118 160 L 118 127.89" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 118 122.64 L 121.5 129.64 L 118 127.89 L 114.5 129.64 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><rect x="78" y="160" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 200px; margin-left: 79px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">power supply<br />(battery pack)</div></div></div></foreignObject><image x="79" y="186" width="78" height="32" xlink:href="data:image/png;base64,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"/></switch></g></g></g></svg> \ No newline at end of file
diff --git a/docs/img/system-top.svg b/docs/img/system-top.svg
index 0a9e8c0..902fa07 100644
--- a/docs/img/system-top.svg
+++ b/docs/img/system-top.svg
@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="390px" height="231px" viewBox="-0.5 -0.5 390 231" style="background-color: rgb(255, 255, 255);"><defs/><rect fill="#ffffff" width="100%" height="100%" x="0" y="0"/><g><path d="M 188 110 L 228 110 L 228 30 L 169.37 30" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 164.12 30 L 171.12 26.5 L 169.37 30 L 171.12 33.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 130px; margin-left: 214px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Puzzle outputs</div></div></div></foreignObject><image x="214" y="124" width="72" height="15.75" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASAAAAA/CAYAAABAdBV6AAAAAXNSR0IArs4c6QAAEOdJREFUeF7tnQesFUUXxwc1KEGxBbEQNCaCvWDDgmIlgg2ViILYe9eoYMHeQRDQ2EVQUbFRFCuCgmJXiBEhVgKCRozYCcqX33yZm3njltk7u2/ve/dM8hJ4b2d25j8z/znnzDlnW6xYsWKFkiIICAKCQAkItBACKgF1eaUgIAhoBISAZCEIAoJAaQgIAZUGvbxYEBAEhIBkDQgCgkBpCAgBlQa9vFgQEASEgGQNCAKCQGkICAGVBr28WBAQBBoQ0PXXX68GDRpUFSpdunRR6667rtp1111V9+7d1fbbb69atmxZVVv1XGnGjBlqzz33rEDw6KOPqr59+9YzJDL2ZoxAbgTkYtSpUydNZkceeaRaddVVmzGE+Q5NCChfPENa++abb9SkSZPUySefrFq1ahXSVJOp++OPP6rHH39c9e/fX6299tqF97swAjI9P//889WNN96oWrduXfhgmsMLhIDKn8Xff/9d3XfffeqGG25QvXv3VkOHDm32BPT333+rZ555Rl133XVqk002UY899pjWaIouiQTUr18/tfXWW3v14bvvvlMfffSRmjlz5n+ev+WWW9TFF1+sVlllFa+26vkhIaByZ//nn39WJ554oho/frzuyOmnn97sCeivv/5SAwYMUHfeeaceMyaUmiCgrPYHwso+/vhjNXDgQPXKK69UVtIGG2ygnnjiCbXXXnuVu7qawNuFgMqdpJ9++knb3F5++eW6IaA///xTXXjhheree+9t2gRkls6iRYvUKaecol544YXKajrvvPPUbbfdJvaglP0lBCQE1NgINDsCAsBnn31WG6BN2X333bVxa+ONN25sfJvU+4SAyp0ukYCasApmL52FCxdqUXbq1KmVX0+fPl3tscce5a6wGn+7EFC5EyQE1EwI6I8//lDcgD3wwAOVFYVh79BDDy13hdX424WAyp0gIaBmQkCuXsmywhB99NFHV1ZYiO75xRdf6LY+/fRT3R7Xh1dddVWD1Ysln5u80LLddtupJ598UuHbRCmqXdquloC4APj222/V888/r9544w2NC/+n4CTauXNnddhhh6muXbs22pXy8uXL1bvvvqttgUi/n3zyifr111/VGmusoR1V9957b30g7bDDDl43pNVi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"/></switch></g><path d="M 188 150 L 218 150 L 301.63 150" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 306.88 150 L 299.88 153.5 L 301.63 150 L 299.88 146.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><rect x="108" y="90" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 130px; margin-left: 109px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Puzzle box</div></div></div></foreignObject><image x="109" y="123.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 133 30 L 68 30 L 68 110 L 101.63 110" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 106.88 110 L 99.88 113.5 L 101.63 110 L 99.88 106.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 110px; margin-left: 64px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Puzzle inputs</div></div></div></foreignObject><image x="-1" y="104" width="65" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g><ellipse cx="148" cy="7.5" rx="7.5" ry="7.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 148 15 L 148 40 M 148 20 L 133 20 M 148 20 L 163 20 M 148 40 L 133 60 M 148 40 L 163 60" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 67px; margin-left: 148px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">Player(s)</div></div></div></foreignObject><image x="124" y="67.5" width="48" height="17" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 68 150 L 88 150 L 101.63 150" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 106.88 150 L 99.88 153.5 L 101.63 150 L 99.88 146.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 150px; margin-left: 60px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Charger</div></div></div></foreignObject><image x="20" y="144" width="40" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g><path d="M 150 170 L 150 190 L 150 210 M 146 210 L 146 190 L 146 170 M 146 210" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 217px; margin-left: 148px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Wi-Fi</div></div></div></foreignObject><image x="135" y="217.5" width="26" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g><rect x="308" y="90" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-dasharray="3 3" pointer-events="all"/><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 130px; margin-left: 309px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">Bomb</div></div></div></foreignObject><image x="309" y="123.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="389px" height="231px" viewBox="-0.5 -0.5 389 231"><defs/><g><g><path d="M 188 110 L 228 110 L 228 30 L 169.37 30" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 164.12 30 L 171.12 26.5 L 169.37 30 L 171.12 33.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-start; width: 1px; height: 1px; padding-top: 130px; margin-left: 214px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: left;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">puzzle outputs</div></div></div></foreignObject><image x="214" y="124" width="71" height="15.75" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARwAAAA/CAYAAAAyu3fMAAAAAXNSR0IArs4c6QAAE+NJREFUeF7tnQOwJTkXxzM7a9u2bdu2rVobtUbN2rZt21atbdvmfPXL7uk6N6+Rvn2775vvnVO1tfVudwf/JP8cJdNv4MCBA52JIWAIGAININDPCKcBlK0KQ8AQ8AgY4dhEMAQMgcYQMMJpDGqryBAwBIxwbA4YAoZAYwgY4TQGtVVkCBgCRjg2BwwBQ6AxBIxwGoPaKjIEDAEjnC7Ogd9++80NM8wwSQumm24699JLL3WxRVa1IVAvAkY49eKbW7oRThfBt6q7goARTldg/7dSI5wugm9VdwUBI5yuwG6E00XYW6p+9NFH3Xzzzed/O+yww9xee+3VW5pWWzv++usvN9JII7lffvnFLbXUUu7222+vra6wYCOcxqDuWZFpOF0E/7+qjz76aLf77rv3KcJ5+umn3RxzzOH7bITT/TnYWAuMcBqDOrOiVVdd1V133XV9inBOPPFEt+OOOxrhdH/6NdsCI5xm8U6rbeyxx3aff/55nyKctdZay1155ZVGON2ffs22wAinWbzD2t5++203+eSTJz/3FR/OBBNM4D766KPuEs7777/vJp544gT8zTbbzJ199tn+bxbGRRdd5K6//nr3wgsvuC+//NL179/fjTnmmG6mmWZyK6+8slt33XXdkEMOmTuD1l9/fXfJJZck79x3331u4YUXjpp1ww8/vPv555/9u6ONNpr76quvenx36KGHuv322y+qvKyX6Cft1FJXuVUI5+WXX/amwN133+3ee+89jwdXG40xxhiOCbXYYov5cZl55pkr4RH7MY7IG2+80d15553u8ccfd1988YX7+uuv3dBDD+3Ha6KJJvJjveKKK7pZZpmlsNi33nrLTTHFFMl7Cy20kLv//vsLv+MF7Zfh75NOOsltt912/ltwAqMYwZn88MMPJ69usskm7vzzz0/+/vDDD93444/v/2ZdsF4efPBBPx7M1VFGGcWNN954bskll3QbbLCBm3766XOrravPVErdzJkY+fPPP93ggw/e49XPPvvMa0aMA2XBAz/++KN/Fyf0ZJNN5maffXY/xsy/NEmcxkyO0UcfPXlntdVWc1dffbUHEjuX3SBPpppqKnfhhRe6OeecM/M1I5xWImuHcD7++GPv5Lz88ss9wRTJGmus4Y455hhPQnUJ84ToTtEckfqXX355d9xxx7VoF2Hb6lp8VQhn++23dyeffHLS1BdffNGRrLnnnnt6kssbDzboHXbYwR111FF+s06TuvpclXDYTPbff3937LHHut9//z1qGrHRnXvuuT02l4RwYKoRRxwxKWzxxRd3Z511lmcsyChGYLl7773XzTrrrKmvDwqEc/HFF7v11luvpf2d0HDSyi1LOGQhL7PMMok6rBvJbsqE/+6773pgzy6LJjT11FPHDGOpdw466CB34IEH9vimX79+btRRR/UT9KeffurxnM3tlltuydyg6lp84DP33HP79nz//feOXVsEzYc2i8w222wtGvmuu+7qF50I2s+1117b8lsReBtuuKHXksCnKZKlHrSON954w6G9vPPOO0nVww03XKKlyY9oL0KKzKlVVlnF3XDDDaldQ7v5+++/U8kW7faee+5x8847b/JtQjjE5KlchEEZdthhPYHwf9idiieZZBKvQjEhLr30Us/4VCgyzTTTeK0oTSWrm3AAR7elaPDx1J966qnJa+OOO657/vnnWzQ9HtZVbhnCQX2dYYYZEgcn7WIsWOxMppFHHjlZRORVHHLIIS0qNKo/E0lvKkX4FD1nQ9pyyy1bXlthhRV8BGTBBRd0QwwxhH/GhnXTTTf5tmK6i2CS0yatWcuzughHNxYTaIsttkh+KvLh7LHHHl5DEdl777197g4yzzzzuG222cbn9GBCfvvtt+6hhx5yRxxxRI/jKrgVcEE0SThZuBaFxUOMRhhhBLfLLru4lVZayWHVwA2sj08++cSR0wQfYFaKMO8Yy6GGGsr/lBBOOPnxx/zxxx/eBsXXou1pDRQ2+3LLLedQu0RoJD6gUOomnKIFop+zu6Laiww22GDurrvucosuumiZYnq8W6bcMoSDictuKrLAAgu4m2++OZNAKHv11Vf3WoQIC+KUU06p1D/5GKfjtNNO6214kcMPP9ybF1nyww8/OHwxzz33XPIKO/4FF1zQlcVXlnAwGyEQEVkj9BniSdNa0PCYZ2iYIviz0DKYc1qaINmwjiLCwUXy1FNP+WaiROCfQ/PLEsiHDQe/mcg555zjNt10U/9nJuHIy4899liigmZVsvPOO7vjjz8+ebzIIot4zSiU3kI4qNEzzjijd3qJsFsNGDCg0mIsW24s4WBKod2IoPqj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"/></switch></g></g><g><path d="M 188 150 L 218 150 L 301.63 150" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 306.88 150 L 299.88 153.5 L 301.63 150 L 299.88 146.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><rect x="108" y="90" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 130px; margin-left: 109px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">puzzle box</div></div></div></foreignObject><image x="109" y="123.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 133 30 L 68 30 L 68 110 L 101.63 110" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="stroke"/><path d="M 106.88 110 L 99.88 113.5 L 101.63 110 L 99.88 106.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 110px; margin-left: 64px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">puzzle inputs</div></div></div></foreignObject><image x="0" y="104" width="64" height="15.75" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAA/CAYAAAAPKRaqAAAAAXNSR0IArs4c6QAAEe1JREFUeF7tnQPQJTkQx3vPtrVn27Zt27Z9t1dn27avzrZt27axV79U9VS+7CDvzXs78+10V13t3b4kk3Q6/zRzffr3799fjIwDxoFGcqCPAUAj990WbRxwHDAAMEEwDjSYAwYADd58W7pxwADAZMA40GAOGAA0ePNt6cYBAwCTAeNAgzlgANDgzbelGwcMACqUgT/++EOGHXbYZAbTTTedvPLKKxXOKP7TO++8s5x00klJhxtuuEFWXnnl+AGsZS04YABQ4TYYAFTIfPu05QFULQMGAFXvgH3fNIAKZaA3A8Cpp54q1157bcK9ww47TOaff/4Kudm7P/3PP//IyCOPLL/99psstdRScscddwyUBRkADBQ2p3+kNwNAhWwbJD/9zDPPyBxzzOHWZgAwSG7xgIsyAGjIRkcs8+STT5addtrJACCCV4NMEwOAQWYrSy9krbXWkquvvtoAoDQne9EABgC9aLO6PNUJJ5xQPvnkk+oA4MMPP5SJJ544WeZmm20m5557rvtvBPWSSy6RG2+8UV566SX5+uuvZfDBB5exxhpLZpppJhf/XXfddWWooYbKZdP6668vl112WdLm/vvvl4UXXjiKtSOMMIL8+uuvru3oo48u33zzzQD9cEQdcMABUeNlNWKdzNOnbo1bBgBeffVVIfZ+zz33yAcffOD4wdMOY445piBMiy22mNuXmWeeuRQ/sjrH5gHMOeec8vTTT7thJp98cnn77beTIV9//XU555xzBDl47733nANspJFGkokmmkgWWGAB2XrrrWXaaafNnf9FF10kG2+8cdLG378vv/xSzj77bLnzzjvlzTfflB9++EGGH354GWeccWS++eaTNddc09nbRTTBBBPIp59+mjSLfULDt+vpvNpqq/VwnE4//fTCPsbQ33//LUMMMcQATb/44gunOTzwwANuLM7mzz//7NriVJxssslk9tlnlxVXXNHJREiJE/Dbb7+VMcYYI/ldJ8uBX3XVVeXdd9/NnedUU00lF198sbDhWWQA0BNY2gEABHGPPfaQK6+80h34IlpjjTXkuOOOc6DQSYoFgEUXXdQdcIiD9/nnn7t577fffnLUUUfJf//9lzmtPn36yP777y+HHnpoZpvrrrtOVl999eT3U045Rbbffnu56qqrZPPNN5dffvkld9lLL720ACJcZllURwAganDggQfK8ccfL3/++WfU1nIZnH/++TLLLLMk7RMAADVAX6XFF1/coTPoATjEEIhz3333yayzzpravDcAwKWXXirrrbdej/l3QgNIG7dVACBLcJlllklURX+So446qjtY3HIhjT/++E5TmHrqqWO2MapNLABww951111uTOSD+XFATzvttKjv0IiMwx133DG1/c033+xuNyX2ipuVSysPXPzBZphhBnnwwQcFHqZRtwCAeb/11lvC7Y4GpISWwjd94nZH64bY51VWWUVuuumm1Ply+//777+pF8Qwwwwj9957r8w777yubwIAqF98WGnuueeW4YYbzh1o/txhhx3cRyeZZBKnXrzzzjty+eWXC/FgPqY0zTTTODMhTV3pNgDAGH8uRRKG1/X0009Pmo033njy4osv9tCElOHdGLcVAEC1Q1BRa5XYi4MPPtgdgFFGGcX99Y8//uhiyP369euhXiJQCJEP8kX8yfs9FgCWXXZZuf32291QQw89tLtt1157beF2x2xEfefAImNoB3fffbccfvjh7t+VMP8+++wzGXHEEQeY0m233SbLLbdc8vdbbbWVU7O5tNB6dt11V1liiSUEEPz999+dbAI+AIdPW2yxhTMXBiYA6Lc4S1NMMUXy6aIwIKY581WCL6xzpZVWEjRxeMlZgGePPfaYO6MPPfRQ0h5Z4JvsRwIAoTBiz//111+Ocahw/gR9JoHubAAqiRITxIcQUrcBoBWBvvXWW2X55ZdPugw22GBO+FBZy1Ar47YCAJhk119/fTI1bORbbrkl80AzNqox81HadtttW7p5OwEAyAaHVAkz4Pvvv5drrrlGVlhhhdRPfPTRRzLjjDM6MFO68MILZaONNhqgPWCHVqSkcss+ckMCHmmE+gxIKnG7vvbaazLllFMO0LxbGkC7AOD7Vbhon3jiCZltttkytwsw4LLDPFI677zzZNNNN80GAG34+OOPC9pAHu2yyy5y4oknJk0WWWQRpznUFQBwnCBg3KpK++yzj7t5ylCr48YCAKo/t78Sjj5uc/7MI9Rt1H7VGoYcckh3K/i+nnbXG6sBALI+CPE9Yt5olHm09957Ox+BEjf7mWeeWQgANMCex9mYp+1wKDg0zz//fDLmIYcc4uzqkOoE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"/></switch></g></g><g><ellipse cx="148" cy="7.5" rx="7.5" ry="7.5" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" pointer-events="all"/><path d="M 148 15 L 148 40 M 148 20 L 133 20 M 148 20 L 163 20 M 148 40 L 133 60 M 148 40 L 163 60" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 67px; margin-left: 148px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: nowrap;">player(s)</div></div></div></foreignObject><image x="124.5" y="67.5" width="47" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g><g><path d="M 68 150 L 88 150 L 101.63 150" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="stroke"/><path d="M 106.88 150 L 99.88 153.5 L 101.63 150 L 99.88 146.5 Z" fill="rgb(0, 0, 0)" stroke="rgb(0, 0, 0)" stroke-miterlimit="10" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe flex-end; width: 1px; height: 1px; padding-top: 150px; margin-left: 60px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: right;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">charger</div></div></div></foreignObject><image x="23" y="144" width="37" height="15.75" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJQAAAA/CAYAAAAG5+H5AAAAAXNSR0IArs4c6QAADn1JREFUeF7tnAmwllMYx5+UVkUppJRBixhbhJQ2Sw3tIUlIlKUiKtnaNwrtommnsk070WKpyNImLdooFaIsRVpkfmfmvHO+977r5733NrfzzNy5c7/vvOc85zn/8+zvzXX06NGjYslKICEJ5LKASkiSdholAQsoC4REJWABlag47WQWUBYDiUrAAipRcdrJLKAsBhKVgAVUouK0k2UJoE466STZv3+/kvapp54qv/zyi5V8DpWABVQOPdjs2pYFVHZJPoeuawGVQw82u7ZlAZVdks+h61pA5dCDza5tWUBll+Rz6LoWUDn0YLNrW4GAWrt2rbz11lvywQcfyPfffy+7d++W3Llzy2mnnSaVK1eW+vXry2233Sb58uUL5N/MQ51++uny448/OuMXLlwoEyZMkM8++0x++OEHOXTokBQtWlTOP/98ueGGG6Rdu3ZSrFixWPKBV/j++OOPhT3AN3mw/PnzyymnnCKVKlWSa665Ru666y4pW7Zs6Ny//fab4klT27Zt5eWXX1Z/zps3TwYNGiTLly+XvXv3Kl798mz//vuvvP322/LOO+/IV199peRw8OBBOeOMM+TKK6+UVq1ayU033eSsc//998urr77q/L1z504pWbJkKL8//fSTWgfe1q1bp/b/119/SfHixQX5V6tWTa2DfHPlyhU63yOPPCJDhgxxxu3atUvx/Pvvv0vv3r1lxowZsn37dvnnn3+821f27NkjnTt3lvHjxwtCCKJSpUop4d58882+w0xAnXXWWbJt2zb5448/lABhJohOPvlkmTp1qtStWzd04/v27ZPHHntMxo4dK4cPHw4df8IJJ8hDDz0kzz33nAKbHx04cEAKFCjgfA3fXIKJEycqUJrkl7gF2Iz98ssvA/mqV6+e2m+RIkWkadOmCnya/vzzT0GWfsSB9unTR1588UUnkRy0GEph6NChUrVq1UCennjiCRk4cKAzZsuWLQqc1atXl1WrVqU8m0FDgb7rr79evvnmm9AD0QNAOQhu37695zMmoMqXL6+YqFWrltJKUShv3rzyxRdfyEUXXeQ7HGFfe+21snLlSs8x8OjXnMp+58yZIyeeeKLv/IBPP3/LLbfI8OHD5ZxzzslwcF6A2rhxoxI+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"/></switch></g></g><g><path d="M 150 170 L 150 190 L 150 210 M 146 210 L 146 190 L 146 170 M 146 210" fill="none" stroke="rgb(0, 0, 0)" stroke-miterlimit="1.42" stroke-dasharray="3 3" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 217px; margin-left: 148px;"><div data-drawio-colors="color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 11px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; background-color: rgb(255, 255, 255); white-space: nowrap;">Wi-Fi</div></div></div></foreignObject><image x="135" y="217.5" width="26" height="15.75" xlink:href="data:image/png;base64,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"/></switch></g></g><g><rect x="308" y="90" width="80" height="80" fill="rgb(255, 255, 255)" stroke="rgb(0, 0, 0)" stroke-dasharray="3 3" pointer-events="all"/></g><g><g transform="translate(-0.5 -0.5)"><switch><foreignObject pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" style="overflow: visible; text-align: left;"><div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 130px; margin-left: 309px;"><div data-drawio-colors="color: rgb(0, 0, 0); " style="box-sizing: border-box; font-size: 0px; text-align: center;"><div style="display: inline-block; font-size: 12px; font-family: Arial; color: rgb(0, 0, 0); line-height: 1.2; pointer-events: all; white-space: normal; overflow-wrap: normal;">bomb</div></div></div></foreignObject><image x="309" y="123.5" width="78" height="17" xlink:href="data:image/png;base64,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"/></switch></g></g></g></svg> \ No newline at end of file
diff --git a/docs/makefile b/docs/makefile
index eb54a80..d180398 100644
--- a/docs/makefile
+++ b/docs/makefile
@@ -20,3 +20,9 @@ ASCIIDOCTOR_ARGS += --backend pdf
%.pdf: %.adoc $(PDFDEPS)
bundle exec asciidoctor $(ASCIIDOCTOR_ARGS) $<
+%.svg: %.puml
+ plantuml -tsvg $<
+
+design.pdf: img/software-components.svg
+design.pdf: img/sequence-puzzle-module-init.svg
+
diff --git a/docs/reqs.adoc b/docs/reqs.adoc
index 8ad24a8..a221173 100644
--- a/docs/reqs.adoc
+++ b/docs/reqs.adoc
@@ -108,7 +108,7 @@ describes all functional requirements of the puzzle box.
=== The puzzle box
.Puzzle box specifications
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -165,7 +165,7 @@ describes all functional requirements of the puzzle box.
=== The bomb
.Bomb specifications
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -198,7 +198,7 @@ describes all functional requirements of the puzzle box.
=== The game
.General game specifications
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -239,7 +239,7 @@ describes all functional requirements of the puzzle box.
==== NeoTrellis puzzle
.NeoTrellis puzzle requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -262,7 +262,7 @@ describes all functional requirements of the puzzle box.
==== Software puzzle
.Software puzzle requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -297,7 +297,7 @@ The specific details for this puzzle are not present in the previous
documentation. Due to time constraints, the section will be left empty.
.Automation puzzle requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -308,7 +308,7 @@ documentation. Due to time constraints, the section will be left empty.
==== Hardware puzzle
.Hardware puzzle requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -397,7 +397,7 @@ documentation. Due to time constraints, the section will be left empty.
==== Vault puzzle
.Vault puzzle requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -447,7 +447,7 @@ documentation. Due to time constraints, the section will be left empty.
=== Battery
.Battery requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -464,7 +464,7 @@ documentation. Due to time constraints, the section will be left empty.
=== Network Communication
.Communication requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -477,7 +477,7 @@ documentation. Due to time constraints, the section will be left empty.
=== Framework
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -497,7 +497,7 @@ documentation. Due to time constraints, the section will be left empty.
=== Puzzle box hub
.Puzzle box hub general requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -516,7 +516,7 @@ technical specifications of the puzzle box.
=== Wireless communication
.Wireless communication requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -527,7 +527,7 @@ technical specifications of the puzzle box.
=== Framework
.Development framework requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -543,14 +543,17 @@ technical specifications of the puzzle box.
| <<req:135>> | <<must>> |
[[req:135,R-135]] Puzzle modules are initialized by the main controller module.
-| <<req:165>> | <<must>> |
+| <<req:165>> | <<wont>> |
[[req:165,R-165]] Puzzle modules repeatedly send 'update' messages to the main controller while their global state is 'uninitialized'
+
+| <<req:curriculum-cov>> | <<should>> |
+[[req:curriculum-cov,R-169]] External software and libraries that are covered in the standard curriculum should be used where possible
|===
=== Main controller
.Main controller requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -575,7 +578,7 @@ technical specifications of the puzzle box.
=== Puzzle module controller
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -601,7 +604,7 @@ technical specifications of the puzzle box.
=== Vault puzzle
.Vault puzzle requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -627,7 +630,7 @@ technical specifications of the puzzle box.
=== Bomb
.Bomb requirements
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
@@ -650,7 +653,7 @@ This section describes the aspects of the project which have been set as
preconditions and cannot be changed.
.Preconditions
-[cols="8h,~"]
+[cols="9h,~"]
|===
| ID | Precondition
@@ -666,7 +669,7 @@ preconditions and cannot be changed.
This section lists requirements that apply to documentation produced during
this project.
-[cols="8h,5h,~"]
+[cols="9h,6h,~"]
|===
| ID | <<tab:moscow,Pri.>> | Specification
diff --git a/docs/research.adoc b/docs/research.adoc
index a6ef255..1cd6150 100644
--- a/docs/research.adoc
+++ b/docs/research.adoc
@@ -1,7 +1,7 @@
:document: Research
include::share/meta.adoc[]
-== Microcontrollers used in the current state.
+== Microcontrollers used in the current state (Elwin)
=== Research
@@ -39,7 +39,7 @@ see <<fig:hardware-pcb>>. The other custom-made PCB's do not have any
microcontroller installed but seem to be made to be used by a ESP32-PICO-KIT
V4/V4.1.
-=== Summery
+=== Summary
There seems to be four games implemented where of only one may work because of
its integrated ESP32, the other three also may work if the missing ESP32's are
@@ -87,7 +87,7 @@ Issues
. Button row 4, col 1 for the safe side needs to be replaced (missing a pin)
. LED strips for the software and hardware sides only work for 50%.
-==== (Appendix Loek)
+==== Appendix (Loek)
The puzzle bus connector (see <<fig:bus-connector>>) appears to have 10
conductors in total. The hardware schematics from 21-22 reveal the pinout of
@@ -112,7 +112,7 @@ Source: cite:[2122_design] +
(Connector key is next to pin 5)
====
-== Controllers
+== Controllers (Loek)
To mitigate power consumption issues discovered by the 21-22 group, new
controllers were chosen for this year's (23-24) run of the puzzle box project.
@@ -143,6 +143,12 @@ than the other options. It also happens to be less expensive than all other
options. Due to these reasons, the RP2040 was chosen as main controller MCU.
The Raspberry Pi Pico W board is utilized during development.
+NOTE: This was written while we did not know the puzzle bus specifically
+requires slave-addressible I^2^C multi-master controllers to function properly.
+The RP2040 was still used, but has required implementing workarounds. Please
+see the handover report for more details on how this impacted the project
+cite:[handover].
+
[[tab:main-mcu]]
.Main controller MCU candidates
[%autowidth]
@@ -173,10 +179,10 @@ manufacturers: Atmel, STMicroelectronics, Raspberry Pi.
All the MCUs listed in <<tab:pm-mcu>> support some version of a low-power mode.
The RP2040 is again included and appears here because it supports clock speed
-configuration and has a clock gate for each peripheral [2], which may make it a
-feasible option with regards to power consumption. Choosing the RP2040 may also
-simplify the development process as only a single MCU toolchain needs to be
-maintained.
+configuration and has a clock gate for each peripheral cite:[rp2040ds], which
+may make it a feasible option with regards to power consumption. Choosing the
+RP2040 may also simplify the development process as only a single MCU toolchain
+needs to be maintained.
The Microchip PIC16F15276 is the most power efficient on this list and is the
recommended MCU for puzzle modules. It supports both extreme underclocking and
@@ -187,6 +193,10 @@ Because this year's run of this project was carried out by a team consisting
only of software students, this choice remains as a recommendation. The puzzle
box hardware may still use the ESP32 development kits from the 21-22 group.
+NOTE: This was written while we did not know the puzzle bus specifically
+requires slave-addressible I^2^C multi-master controllers to function properly.
+We have not verified if the PIC16F15276 supports this feature.
+
[[tab:pm-mcu]]
.Puzzle module controller MCU candidates
[%autowidth]
@@ -205,71 +215,6 @@ the Raspberry Pi RP2040 on the Raspberry Pi Pico W. The recommended MCU for new
puzzle modules is the Microchip PIC16F15276. The existing puzzle modules still
utilize the ESP32 development kits chosen by the 21-22 group.
-== Main Controller OS
-
-Because the hardware produced by the 21-22 group uses a Raspberry Pi 3B+ as
-main controller, the usage of this specific board was turned into a
-prerequisite for this project (??). The Raspberry Pi 3B+ uses the Broadcom
-BCM2837 chipset, which supports the aarch64 instruction set cite:[rpicpu].
-Because the puzzle box should be able to run on battery power (??), the CPU
-should be under as little load as possible to preserve power. Choosing the
-right operating system is crucial to ensure maximum control over which
-processes consume CPU resources. This section indexes the available operating
-systems that support the aarch64 instruction set to support the decision for
-main controller OS in the design document [??].
-
-Each operating system is evaluated on the following criteria:
-
-* Number of 'base' software packages (pre-installed software)
-* Size of base installation (base disk utilization)
-* Time required to get set-up
-* Software iteration time (amount of work required to complete a
- compile-upload-run cycle)
-* Whether it is covered by the standard curriculum at Avans University of
- Applied Sciences
-
-All of these factors (except for curriculum coverage) should be low. This means
-that operating systems that are minimalistic by default are preferred.
-
-=== Raspberry Pi OS Lite (Debian)
-
-The manufacturer of the Raspberry Pi boards publishes a modified version of the
-Debian Linux distribution which is aimed at general-purpose users [??]. It
-comes with an easy-to-use installer, and is the only OS officially supported by
-the manufacturer of this board. All the required drivers come pre-installed,
-which means this OS has very little setup time.
-
-Raspberry Pi OS comes in 3 different varieties [??], the 'Light' variant of
-which is the most minimalistic. This variant comes with the least number of
-pre-installed software packages and has a base image size of 2.6 GiB after
-extracting the archive from the official download page [??].
-
-This exact OS is not covered in the normal curriculum, but other derivative
-distributions of Debian are, so this OS is be considered familiar.
-
-=== Void Linux
-
-=== Linux From Scratch
-
-=== Bare-metal Firmware
-
-=== Conclusions
-
-<<tab:main-os>> summarizes the considered operating systems based on the
-criteria outlined at the start of this section.
-
-[[tab:main-os]]
-.Main controller OS comparison
-[%autowidth]
-|===
-| | Packages | Size | Set-up time | Iteration time | Covered
-
-| Raspberry Pi OS Lite | 592 | 2.6 GiB | Medium | Short | Yes
-| Void Linux | 126 | 334 MiB | Short | Short | No
-| Linux from scratch | n/a | 25+ MiB | Long | Long | Yes
-| Bare-metal firmware | n/a | n/a | Long | Long | No
-|===
-
== Unit Testing Framework Research (Thomas)
=== Research question
@@ -400,6 +345,114 @@ testing. Including mocking tests, a large amount of assertions, multiple test
with different input support, and lastly being supported in the newest
non-experimental version of {cpp}.
+== I^2^C (Thomas)
+
+=== Research question
+
+How can we use I^2^C for the puzzle module detection and communication?
+
+=== Puzzle Module and Main Controller Communication
+
+Research from project group 21/22 shows that the I^2^C protocol is the best
+option for communication between the puzzle modules and the main controller.
+This research section extends the previous section about which MCU is suitable
+for the puzzle bus, as we have found vital I^2^C limitations with the
+controller we had chosen. See the handover document for the found limitations.
+
+// TODO: REFERENCES
+// TODO: Find synonym for 'vital'
+
+==== MCUs Supporting Master Addressable as Slave
+
+===== Atmega328p
+
+The Atmega328p has multi-master support, where the MCU is addressable as a
+slave while being in master mode. This has been confirmed using the Arduino
+wire library on both the Arduino Mega and the Arduino Uno.
+
+===== PIC16F15276 & ESP32
+
+Both the PIC16F15276 cite:[PICData] and the ESP32 MCUs show possibilities to be addressable as a slave while being in master mode. However, at the moment of writing this
+has yet to be tested.
+
+// TODO: Add the following reference:
+// PIC16F15276 - 25.2.4.3
+// https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/PIC16F15256-74-75-76-Microcontroller-Data-Sheet-40002305.pdf
+
+// TODO: Add the following reference:
+// https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32/api-reference/peripherals/i2c.html
+// https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf#i2c
+// https://www.bitsandparts.nl/documentation/482/ESP32_Specifications_EN_v1.pdf
+
+==== Alternatives
+
+===== PIC16F15276 Registers
+
+In the case of the PIC16F15276 cite:[PICData] not support master addressable as slave the
+following approach would most likely work. As the PIC16F15276 uses specific
+registers for its master receive functions, namely the RCEN register, it can
+be manually set to receive data from the I^2^C bus. However, this also has
+yet to be tested.
+
+===== Multiple I^2^C Peripherals
+
+==== ESP32 & RP2040
+
+The ESP32 cite:[I2CESPAPI] cite:[I2CESPTECH] cite:[ESPSPECS] and the RP2040 both
+have multiple peripherals for I^2^C communication, while also supporting
+simultaneous configuration. This allows both two I^2^C peripherals to be active,
+one being configured as a master and the other being configured as a slave. This
+enables the controller to send and receive data to the I^2^C bus without much
+difficulty. This does introduce increased code complexity but is a valid option
+if it is succesful in testing.
+
+// TODO: Add the following reference:
+// https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32/api-reference/peripherals/i2c.html
+// https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf#i2c
+// https://www.bitsandparts.nl/documentation/482/ESP32_Specifications_EN_v1.pdf
+
+=== Puzzle Module Detection
+
+Puzzle module detection is vital to the puzzelbox, as this allows changing the
+puzzles without much software or hardware configuration needed. An option will
+be given for the choice of main controller (RP2040); namely to scan the full
+I^2^C bus for responsive slaves. The RPI Pico SDK has an API for I^2^C which
+also supports functions create a bus scanning function. An example of this
+bus scan function, according to the API examples, can be found in the pseudo
+code below.
+
+[source, c]
+----
+#include <stdio.h>
+#include "pico/stdlib.h"
+#include "hardware/i2c.h"
+
+void bus_scan() {
+ int ret;
+ uint8_t rxdata;
+
+ for (int addr = 0; addr < (1 << 7); ++addr) {
+ ret = i2c_read_blocking(i2c_default, addr, &rxdata, 1, false);
+ printf(ret < 0 ? "." : "@");
+ printf(addr % 16 == 15 ? "\n" : " ");
+ }
+ printf("Done.\n");
+}
+----
+
+The bus scan function tries to read data from all possible I^2^C addresses,
+and prints a table which shows what the addresses are from found I^2^C
+slaves. This is possible due to the i2c_read_blocking function, which returns
+the length of the read data if the slave address is in use (in this case 1) or
+a number below 0 if the slave address is not in use. The puzzelbox, however,
+has the 'Neotrellis' puzzle which also uses I^2^C to function. The bus scan
+function would also see the 'Neotrellis' rgb matrix as a puzzle module (slave)
+using this implementation. This can easily be fixed using a handshake between
+puzzle modules and the main controller, as the 'Neotrellis' rgb matrix cannot
+answer this handshake and is therefor not recognized as a puzzle module.
+
+// TODO: references (API) & code block naming?
+
== Original Puzzle Box Functionality Research (Thomas)
=== Research question
@@ -522,7 +575,7 @@ The way these puzzles are solved has been summarized in this research document,
but the most complete versions of how to solve these puzzles are given in the
group's respective design document.
-== Research of hardware designs of previous groups (21-22 and 22-23)
+== Research of hardware designs of previous groups (21-22 and 22-23) (Lars)
This part of the research looks at the hardware designs of the previous groups
that did this project. These are compared with each other and finally the
diff --git a/docs/share/refs.bib b/docs/share/refs.bib
index b6fe625..6386fec 100644
--- a/docs/share/refs.bib
+++ b/docs/share/refs.bib
@@ -166,6 +166,14 @@
year = {2024},
}
+@techreport{handover,
+ author = {Blansch, Loek Le and Hammer, Elwin and Faase, Lars and in 't Anker, Thomas},
+ title = {Handover Report},
+ location = {'s-Hertogenbosch},
+ publisher = {Avans University of Applied Sciences},
+ year = {2024},
+}
+
@techreport{2021_design,
author = {Creemers, Merel and van Wiechen, Joost and Lengowski, Vincent and Maas, Justin},
title = {Ontwerpdocument},
@@ -192,3 +200,57 @@
publisher = {Avans University of Applied Sciences},
year = {2022},
}
+
+@online{Joh21,
+ author = {Johnston, P.},
+ title = {Embedded systems testing resources},
+ url = {https://embeddedartistry.com/blog/2018/10/18/embedded-systems-testing-resources/},
+ month = jun,
+ msbib-day = {10},
+ msbib-accessed = {2024-02-25},
+ year = {2021},
+}
+
+@online{RPI23,
+ title = {Hardware APIs - Hardware I2C},
+ url = {https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#hardware_i2c},
+ month = jun,
+ msbib-day = {14},
+ year = {2023},
+ msbib-accessed = {2024-05-11},
+}
+
+@techreport{pbdox,
+ title = {puzzlebox Doxygen documentation},
+ author = {Blansch, Loek Le and Hammer, Elwin and Faase, Lars and in 't Anker, Thomas},
+ url = {https://media.pipeframe.xyz/puzzlebox/23-24/doxygen},
+ year = {2024},
+}
+
+@online{PICData,
+ title = {PIC16F15276 - 25.2.4.3},
+ url = {https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/PIC16F15256-74-75-76-Microcontroller-Data-Sheet-40002305.pdf},
+ author = {{Microchip}},
+ year = {2022},
+}
+
+@online{I2CESPAPI,
+ title = {I2C Driver - ESP32},
+ url = {https://docs.espressif.com/projects/esp-idf/en/v4.3/esp32/api-reference/peripherals/i2c.html},
+ author = {{Espressif Systems}},
+ year = {2021},
+}
+
+@online{I2CESPTECH,
+ title = {ESP32 Technical Reference Manual},
+ url = {https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf#i2c},
+ author = {{Espressif Systems}},
+ year = {2024},
+}
+
+@online{ESPSPECS,
+ title = {ESP32 Specifications},
+ url = {https://www.bitsandparts.nl/documentation/482/ESP32_Specifications_EN_v1.pdf},
+ author = {{Espressif Systems}},
+ year = {2015},
+}
diff --git a/docs/theme.yml b/docs/theme.yml
index b26ad75..49f729f 100644
--- a/docs/theme.yml
+++ b/docs/theme.yml
@@ -61,6 +61,7 @@ toc:
caption:
align: center
end: bottom
+ margin_inside: 6pt
image:
align: center
@@ -98,3 +99,10 @@ footer:
center:
content: '{page-number}'
+admonition:
+ column_rule_color: '#000000'
+ column_rule_width: 1pt
+ padding: [3pt, 6pt, 3pt, 6pt]
+ label:
+ font_style: bold
+
diff --git a/lib/Arduino-CMake-Toolchain b/lib/Arduino-CMake-Toolchain
-Subproject e745a9bed3c3fb83442d55bf05630f31574674f
+Subproject 953b2e63ddf434868bfba60244fb714262fce5f
diff --git a/lib/i2ctcp/i2ctcpv1.h b/lib/i2ctcp/i2ctcpv1.h
index 799b668..e9bc0d9 100644
--- a/lib/i2ctcp/i2ctcpv1.h
+++ b/lib/i2ctcp/i2ctcpv1.h
@@ -2,43 +2,69 @@
#include <stddef.h>
#include <stdint.h>
+#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
-/** \brief I2C over TCP message (v1) */
-struct i2ctcp_msg {
- uint16_t addr; //!< I^2^C address
+/**
+ * \defgroup i2ctcp i2ctcp
+ * \brief I2C over TCP
+ *
+ * This library includes protocol (de)serialization functions for sending and
+ * receiving I2C messages over TCP. These functions are used by the \ref main
+ * "main controller" and the \ref pbc "puzzle box client (pbc)". This library
+ * does not include any puzzle bus specific code.
+ *
+ * mpack is used for the actual (de)serialization, and the functions in this
+ * library act as helpers for parsing from chunked data streams.
+ *
+ * To use these functions, include the following statement in your
+ * CMakeLists.txt:
+ *
+ * ```cmake
+ * # include pbdrv
+ * add_subdirectory(lib/i2ctcp)
+ *
+ * # link with executable
+ * target_link_libraries(main i2ctcp)
+ * ```
+ *
+ * \{
+ */
+
+//! I2C over TCP message (v1)
+typedef struct {
+ uint16_t addr; //!< I2C address
char * data; //!< message content
size_t length; //!< message size
size_t _rdata; //!< \private remaining bytes to read until message is complete
-};
-typedef struct i2ctcp_msg i2ctcp_msg_t;
+} i2ctcp_msg_t;
/**
* \brief Read chunk of input stream, and store resulting message in \p target
*
* This function is called for each chunk of data from an input stream, and
* will parse the next puzzle bus message into \p target. The input stream is
- * assumed to only contain messages encoded by \p i2ctcp_write()
+ * assumed to only contain messages encoded by \c i2ctcp_write()
*
- * \param target pointer to struct that will contain the finished message data
- * \param buf pointer to input stream data chunk
- * \param buf_sz size of \p buf
+ * \param target Pointer to struct that will contain the finished message data
+ * \param buf Pointer to input stream data chunk
+ * \param buf_sz Size of \p buf
*
* \returns Integer representing amount of bytes required to finish message, or
* -1 if the message header could not be read. If this function returns 0, the
* message in \p target is complete.
*
- * \note target->data will automatically be allocated by this function, even if
- * the message is not fully parsed. This variable must be `free()`d by the
+ * \note \p target->data will automatically be allocated by this function, even
+ * if the message is not fully parsed. This variable must be free'd by the
* caller after each complete message to prevent memory leaks.
*/
int i2ctcp_read(i2ctcp_msg_t * target, const char * buf, size_t buf_sz);
/**
- * \brief reset the remaining message data counter
+ * \brief Reset the remaining message data counter
*
* Calling this function has the effect of forcing \c i2ctcp_read() to parse
* the next buffer chunk as the start of a new message. This function may be
@@ -52,19 +78,21 @@ void i2ctcp_read_reset(i2ctcp_msg_t * target);
*
* This function allocates a buffer large enough to fit the message specified
* in \p target, and encodes the data in \p target in a format that can be
- * decoded later using \p i2ctcp_read()
+ * decoded later using \c i2ctcp_read().
*
- * \param target pointer to struct that contains the message data
- * \param buf pointer to \c char* that will contain the formatted message
- * \param buf_sz pointer to \c size_t that will represent the final size of \p buf
+ * \param target Pointer to struct that contains the message data
+ * \param buf Pointer to \c char* that will contain the formatted message
+ * \param buf_sz Pointer to \c size_t that will represent the final size of \p buf
*
- * \returns boolean true if a the message could be encoded successfully, false
- * if there was some kind of error
+ * \returns Boolean \c true if a the message could be encoded successfully, \c
+ * false if there was some kind of error
*
- * \note the pointer stored in \p buf must be `free()`d by the caller afterwards
+ * \note The pointer stored in \p buf must be free'd by the caller afterwards
*/
bool i2ctcp_write(const i2ctcp_msg_t * target, char ** buf, size_t * buf_sz);
+/// \}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/i2ctcp/readme.md b/lib/i2ctcp/readme.md
deleted file mode 100644
index d5bfe6d..0000000
--- a/lib/i2ctcp/readme.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# i2ctcp (I<sup>2</sup>C over TCP)
-
-This folder includes protocol (de)serialization functions for sending and
-receiving I<sup>2</sup>C messages over TCP. These functions are used by the
-[main controller](../main) and the [puzzle box client (pbc)](../client). This
-folder does not include any puzzle bus specific code, and the headers for
-puzbus are in the [shared](../shared) folder instead.
-
-[MessagePack][msgpack] (specifically the [mpack][mpack] implementation) is used
-for the actual serialization/deserializtion, and the functions in this folder
-act as helpers for parsing from chunked data streams.
-
-To use these functions, include the following statement in your CMakeLists.txt:
-```cmake
-include(../i2ctcp/include.cmake)
-```
-
-The functions are available by `#include`ing the `i2ctcpv1.h` header, and are
-extensively documented using Doxygen-style comments.
-
-[msgpack]: https://msgpack.org/
-[mpack]: https://github.com/ludocode/mpack/
-
-
-
diff --git a/lib/mpack/mpack.h b/lib/mpack/mpack.h
index 7c0c089..33521c4 100644
--- a/lib/mpack/mpack.h
+++ b/lib/mpack/mpack.h
@@ -2,18 +2,39 @@
#include "src/src/mpack/mpack.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \defgroup mpack mpack
+ * \brief Mpack extensions specific to this project
+ *
+ * The mpack folder under `lib/` contains a CMakeLists.txt for integrating the
+ * mapck library with CMake, and includes an extension in the form of an
+ * additional utility function.
+ *
+ * \{
+ */
+
/**
- * \brief read remaining bytes in reader without opening a tag first
+ * \brief Read remaining bytes in reader without opening a tag first
*
- * \param reader pointer to mpack reader object
- * \param p pointer to write data to
- * \param count maximum number of bytes to read
+ * \param reader Pointer to mpack reader object
+ * \param p Pointer to write data to
+ * \param count Maximum number of bytes to read
*
* This function reads *up to* the amount of bytes specified in \p count, or
* less if there is less remaining data in the buffer. If \p count is equal to
* 0, all remaining data in the buffer is read.
*
- * \return amount of bytes read
+ * \return Amount of bytes read
*/
size_t mpack_read_remaining_bytes(mpack_reader_t * reader, char * p, size_t count);
+/// \}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/lib/pbdrv/CMakeLists.txt b/lib/pbdrv/CMakeLists.txt
index 998ed4d..903a3b4 100644
--- a/lib/pbdrv/CMakeLists.txt
+++ b/lib/pbdrv/CMakeLists.txt
@@ -23,7 +23,7 @@ add_library(pbdrv STATIC
pb-buf.c
)
target_include_directories(pbdrv SYSTEM INTERFACE .)
-target_link_libraries(pbdrv mpack)
+target_link_libraries(pbdrv PRIVATE mpack)
# puzzle bus *module* specific code
add_library(pbdrv-mod OBJECT
@@ -32,9 +32,9 @@ add_library(pbdrv-mod OBJECT
pb-route.c
)
target_include_directories(pbdrv-mod SYSTEM INTERFACE .)
-target_link_libraries(pbdrv-mod pbdrv)
+target_link_libraries(pbdrv-mod PUBLIC pbdrv)
# puzzle bus drivers
include(drv/arduino/include.cmake)
-# include(drv/rp2040/include.cmake) # please see /main/pbdrv.h
+include(drv/rp2040/include.cmake)
diff --git a/lib/pbdrv/drv/arduino/include.cmake b/lib/pbdrv/drv/arduino/include.cmake
index 1e2ff08..5ec1124 100644
--- a/lib/pbdrv/drv/arduino/include.cmake
+++ b/lib/pbdrv/drv/arduino/include.cmake
@@ -3,7 +3,7 @@ if(NOT DEFINED ARDUINO)
endif()
target_sources(pbdrv-mod PRIVATE "${CMAKE_CURRENT_LIST_DIR}/mod.cpp")
-target_link_arduino_libraries(pbdrv-mod core Wire)
+target_link_arduino_libraries(pbdrv-mod PRIVATE core Wire)
# freertos is used to defer the handling of i2c messages outside the receive
# interrupt service routine
diff --git a/lib/pbdrv/drv/arduino/index.dox b/lib/pbdrv/drv/arduino/index.dox
new file mode 100644
index 0000000..03510dd
--- /dev/null
+++ b/lib/pbdrv/drv/arduino/index.dox
@@ -0,0 +1,25 @@
+// vim:ft=doxygen
+/**
+\ingroup pb_drv
+\defgroup pb_drv_arduino Arduino
+\brief Arduino ATmega (w/ Arduino-CMake-Toolchain) driver
+
+This driver is known to work with the following MCUs:
+- ATmega328P (Arduino Uno)
+- ATmega2560 (Arduino Mega)
+
+\par Usage
+- Link the \c pbdrv-mod library with your main executable
+
+\note This driver is automatically enabled if the variable \c ARDUINO is
+defined in your CMakeLists.txt (it is by default when using
+Arduino-CMake-Toolchain).
+
+\note This driver automatically includes the \ref pb_ext_freertos
+"FreeRTOS extension" for deferring calls to \c pb_i2c_recv() from the I2C ISR.
+
+A complete example for this driver is available in the \ref puzzle/dummy
+folder.
+
+*/
+
diff --git a/lib/pbdrv/drv/arduino/mod.cpp b/lib/pbdrv/drv/arduino/mod.cpp
index 9130334..c381077 100644
--- a/lib/pbdrv/drv/arduino/mod.cpp
+++ b/lib/pbdrv/drv/arduino/mod.cpp
@@ -1,7 +1,3 @@
-#ifndef ARDUINO
-#error This driver only works on the Arduino platform!
-#endif
-
#include <Arduino.h>
#include <Wire.h>
#include <avr/delay.h>
@@ -42,7 +38,17 @@ static void pb_setup() {
Wire.onReceive(recv_event);
}
+/**
+ * \ingroup pb_drv_arduino
+ * \warning This function includes a hard-coded 10ms delay before sending. This
+ * is to work around a weird issue where the Arduino pulls both SDA and SCL low
+ * while attempting to initiate an I2C transmission. We were able to verify
+ * that the Arduino correctly handles bus arbitration under a test scenario
+ * with 2 Uno's, but ran into issues while integrating the Arduino's with the
+ * RP2040.
+ */
__weak void pb_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) {
+ vTaskDelay(10 / portTICK_PERIOD_MS); // prevent bus collisions
Wire.beginTransmission((int) addr);
Wire.write(buf, sz);
Wire.endTransmission(true);
@@ -64,7 +70,20 @@ void loop_task() {
}
}
-//! Application entrypoint
+/**
+ * \ingroup pb_drv_arduino
+ * \brief Application entrypoint
+ *
+ * This function overrides the default (weak) implementation of the \c main()
+ * function in the Arduino framework. No additional setup is required to use
+ * this driver.
+ *
+ * \note I should really be able to use Arduino's initVariant function for
+ * this, but I can't seem to get it to link properly using the CMake setup in
+ * this repository. Overriding the main() function seems to work, and the
+ * USBCON thing in the default Arduino main() function isn't needed because
+ * puzzle modules are likely not using USB.
+ */
int main(void) {
init(); // call arduino internal setup
setup(); // call regular arduino setup
@@ -74,11 +93,3 @@ int main(void) {
return 0;
}
-/**
- * \note I should really be able to use Arduino's initVariant function for
- * this, but I can't seem to get it to link properly using the CMake setup in
- * this repository. Overriding the main() function seems to work, and the
- * USBCON thing in the default Arduino main() function isn't needed because
- * puzzle modules are likely not using USB.
- */
-
diff --git a/lib/pbdrv/drv/index.dox b/lib/pbdrv/drv/index.dox
new file mode 100644
index 0000000..89b9247
--- /dev/null
+++ b/lib/pbdrv/drv/index.dox
@@ -0,0 +1,19 @@
+// vim:ft=doxygen
+/**
+\ingroup pbdrv-mod
+\defgroup pb_drv Drivers
+\brief Platform-specific \ref pbdrv-mod implementations
+
+Like \ref pb_ext "extensions", drivers provide platform-specific
+implementations for various functions used in \ref pbdrv-mod.
+
+If there is no existing driver for your target, you may implement the following
+in order to use \ref pbdrv-mod:
+
+- The \c pb_i2c_recv() function must be **called** for every received I2C
+ message
+- The \c pb_i2c_send() function must be **implemented** using the
+ platform/device-specific I2C write function
+
+*/
+
diff --git a/lib/pbdrv/drv/rp2040/include.cmake b/lib/pbdrv/drv/rp2040/include.cmake
new file mode 100644
index 0000000..6d25e96
--- /dev/null
+++ b/lib/pbdrv/drv/rp2040/include.cmake
@@ -0,0 +1,11 @@
+if(NOT PICO_PLATFORM STREQUAL "rp2040")
+ return()
+endif()
+
+target_sources(pbdrv-mod PRIVATE "${CMAKE_CURRENT_LIST_DIR}/mod.c")
+target_link_libraries(pbdrv-mod PRIVATE hardware_i2c_headers pico_i2c_slave_headers)
+target_include_directories(pbdrv-mod INTERFACE "${CMAKE_CURRENT_LIST_DIR}")
+
+# pico-stdlib is compatible with C stdlib
+include("${CMAKE_CURRENT_LIST_DIR}/../../ext/stdlib/include.cmake")
+
diff --git a/lib/pbdrv/drv/rp2040/index.dox b/lib/pbdrv/drv/rp2040/index.dox
new file mode 100644
index 0000000..eb01d15
--- /dev/null
+++ b/lib/pbdrv/drv/rp2040/index.dox
@@ -0,0 +1,31 @@
+// vim:ft=doxygen
+/**
+\ingroup pb_drv
+\defgroup pb_drv_rp2040 RP2040
+\brief Raspberry Pi Pico and Pico W driver
+
+This driver is known to work with the following MCUs:
+- Raspberry Pi Pico W
+
+\note While the RP2040's datasheet claims it supports multi-master
+configurations by implementing bus arbitration, it does not natively support
+a mode where it is configured as a (multi-)master with a slave address, such
+that it can be addressed by other multi-masters.
+
+\note This driver includes a workaround that uses both I2C peripherals on the
+RP2040. To use this driver, make sure you initialize both I2C peripherals, and
+connect their respective SDA and SCL pins to the same I2C bus.
+
+\par Usage
+- Link the \c pbdrv-mod library with your main executable
+- Call the \c pb_setup() function (from \c <pb-mod.h>) during setup
+
+\note This driver is automatically enabled if the variable \c PICO_PLATFORM is
+equal to \c "rp2040" in your CMakeLists.txt (it is by default when using the
+pico-sdk CMake library).
+
+\note This driver automatically includes the \ref pb_ext_stdlib
+"stdlib extension" as the pico-sdk implements the C standard library.
+
+*/
+
diff --git a/lib/pbdrv/drv/rp2040/mod.c b/lib/pbdrv/drv/rp2040/mod.c
new file mode 100644
index 0000000..1535da9
--- /dev/null
+++ b/lib/pbdrv/drv/rp2040/mod.c
@@ -0,0 +1,49 @@
+#include "pb.h"
+
+#include "pb.h"
+#include "pb-types.h"
+#include "pb-mod.h"
+#include "pb-send.h"
+#include "pb-buf.h"
+
+#include <hardware/i2c.h>
+#include <hardware/gpio.h>
+#include <pico/i2c_slave.h>
+
+#define PB_I2C_S i2c0
+#define PB_I2C_M i2c1
+
+#define BUF_SIZE 256
+
+uint8_t i2c_msg_buf[BUF_SIZE];
+size_t i2c_msg_buf_sz = 0;
+
+// This function is called from the I2C ISR
+static void recv_event(i2c_inst_t *i2c, i2c_slave_event_t event) {
+ switch (event) {
+ case I2C_SLAVE_RECEIVE: {
+ if (i2c_msg_buf_sz == BUF_SIZE) return;
+ i2c_msg_buf[i2c_msg_buf_sz++] = i2c_read_byte_raw(PB_I2C_S);
+ break;
+ }
+ case I2C_SLAVE_FINISH: {
+ pb_i2c_recv(i2c_msg_buf, i2c_msg_buf_sz);
+ i2c_msg_buf_sz = 0;
+ break;
+ }
+ default: break;
+ }
+}
+
+void pb_setup() {
+ i2c_init(PB_I2C_S, PB_CLOCK_SPEED_HZ);
+ i2c_init(PB_I2C_M, PB_CLOCK_SPEED_HZ);
+
+ i2c_slave_init(PB_I2C_S, PB_MOD_ADDR, &recv_event);
+}
+
+__weak void pb_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) {
+ // false to write stop condition to i2c bus
+ i2c_write_timeout_us(PB_I2C_M, addr, buf, sz, false, PB_TIMEOUT_US);
+}
+
diff --git a/lib/pbdrv/drv/rp2040/pb-mod.h b/lib/pbdrv/drv/rp2040/pb-mod.h
new file mode 100644
index 0000000..96edc70
--- /dev/null
+++ b/lib/pbdrv/drv/rp2040/pb-mod.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \ingroup pb_drv_rp2040
+ * \brief Puzzle bus driver setup
+ *
+ * This function must be called from a setup/init function to initialize the
+ * I2C peripherals used by this driver.
+ */
+void pb_setup();
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "../../pb-mod.h"
+
diff --git a/lib/pbdrv/ext/freertos/include.cmake b/lib/pbdrv/ext/freertos/include.cmake
index e7ab7fd..e205c8f 100644
--- a/lib/pbdrv/ext/freertos/include.cmake
+++ b/lib/pbdrv/ext/freertos/include.cmake
@@ -1,9 +1,7 @@
target_sources(pbdrv PRIVATE "${CMAKE_CURRENT_LIST_DIR}/pb-mem.c")
-target_link_libraries(pbdrv
+target_link_libraries(pbdrv PUBLIC
freertos_kernel
freertos_kernel_include
freertos_config
)
-target_sources(pbdrv-mod PRIVATE "${CMAKE_CURRENT_LIST_DIR}/pb-mod.c")
-
diff --git a/lib/pbdrv/ext/freertos/index.dox b/lib/pbdrv/ext/freertos/index.dox
new file mode 100644
index 0000000..7d72918
--- /dev/null
+++ b/lib/pbdrv/ext/freertos/index.dox
@@ -0,0 +1,6 @@
+// vim:ft=doxygen
+/**
+\ingroup pb_ext
+\defgroup pb_ext_freertos FreeRTOS
+\brief FreeRTOS memory management
+*/
diff --git a/lib/pbdrv/ext/freertos/pb-mem.c b/lib/pbdrv/ext/freertos/pb-mem.c
index b18d79f..6647f05 100644
--- a/lib/pbdrv/ext/freertos/pb-mem.c
+++ b/lib/pbdrv/ext/freertos/pb-mem.c
@@ -3,24 +3,29 @@
#include "../../pb-mem.h"
#include "../../pb-types.h"
+/// \ingroup pb_ext_freertos
inline void * pb_malloc(size_t sz) {
return pvPortMalloc(sz);
}
+/// \ingroup pb_ext_freertos
inline void pb_free(void * ptr) {
vPortFree(ptr);
}
+/// \ingroup pb_ext_freertos
__weak inline void * pb_realloc(void * ptr, size_t sz) {
return NULL; // shit out of luck (don't use mpack_writer_init_growable)
}
+/// \ingroup pb_ext_freertos
__weak void * pb_memcpy(void * dest, const void * src, size_t sz) {
for (size_t offset = 0; offset < sz; offset++)
*((char*) dest + offset) = *((char*) src + offset);
return dest;
}
+/// \ingroup pb_ext_freertos
__weak int pb_memcmp(const void * a, const void * b, size_t sz) {
for (size_t offset = 0; offset < sz; offset++) {
int diff = *((char*) a + offset) - *((char*) b + offset);
diff --git a/lib/pbdrv/ext/freertos/pb-mod.c b/lib/pbdrv/ext/freertos/pb-mod.c
deleted file mode 100644
index 75495be..0000000
--- a/lib/pbdrv/ext/freertos/pb-mod.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <FreeRTOS.h>
-#include <task.h>
-
-#include "../../pb-types.h"
-
-__weak void pb_mod_blocking_delay_ms(unsigned long ms) {
- vTaskDelay(ms / portTICK_PERIOD_MS);
-}
-
diff --git a/lib/pbdrv/ext/index.dox b/lib/pbdrv/ext/index.dox
new file mode 100644
index 0000000..f7d2bc6
--- /dev/null
+++ b/lib/pbdrv/ext/index.dox
@@ -0,0 +1,24 @@
+// vim:ft=doxygen
+/**
+\ingroup pbdrv
+\ingroup pbdrv-mod
+\defgroup pb_ext Extensions
+\brief Platform-specific \ref pbdrv implementations
+
+Extensions provide platform-specific implementations for various functions used
+in \ref pbdrv, and allows \ref pbdrv to remain completely portable. Extensions
+are used in both \ref pbdrv and \ref pbdrv-mod.
+
+In order to use an extension, include the appropriate CMake lists file for your
+target platform after the \ref pbdrv include:
+
+```cmake
+# include pbdrv
+add_subdirectory(lib/pbdrv)
+
+# use stdlib extension (for use with C standard library)
+include(lib/pbdrv/ext/stdlib/include.cmake)
+
+```
+
+*/
diff --git a/lib/pbdrv/ext/stdlib/index.dox b/lib/pbdrv/ext/stdlib/index.dox
new file mode 100644
index 0000000..756af1e
--- /dev/null
+++ b/lib/pbdrv/ext/stdlib/index.dox
@@ -0,0 +1,6 @@
+// vim:ft=doxygen
+/**
+\ingroup pb_ext
+\defgroup pb_ext_stdlib stdlib
+\brief C stdlib memory management
+*/
diff --git a/lib/pbdrv/ext/stdlib/pb-mem.c b/lib/pbdrv/ext/stdlib/pb-mem.c
index b260c2c..328efbb 100644
--- a/lib/pbdrv/ext/stdlib/pb-mem.c
+++ b/lib/pbdrv/ext/stdlib/pb-mem.c
@@ -3,22 +3,27 @@
#include "../../pb-mem.h"
+/// \ingroup pb_ext_stdlib
inline void * pb_malloc(size_t sz) {
return malloc(sz);
}
+/// \ingroup pb_ext_stdlib
inline void pb_free(void * ptr) {
free(ptr);
}
+/// \ingroup pb_ext_stdlib
inline void * pb_realloc(void * ptr, size_t sz) {
return realloc(ptr, sz);
}
+/// \ingroup pb_ext_stdlib
void * pb_memcpy(void * dest, const void * src, size_t sz) {
return memcpy(dest, src, sz);
}
+/// \ingroup pb_ext_stdlib
int pb_memcmp(const void * a, const void * b, size_t sz) {
return memcmp(a, b, sz);
}
diff --git a/lib/pbdrv/index.dox b/lib/pbdrv/index.dox
new file mode 100644
index 0000000..8ddcb6a
--- /dev/null
+++ b/lib/pbdrv/index.dox
@@ -0,0 +1,73 @@
+// vim:ft=doxygen
+/**
+
+\defgroup pbdrv pbdrv
+\brief Standalone puzzle bus driver
+
+\ref pbdrv is a standalone portable static library for handling (i.e.
+(de)serialization) of puzzle bus messages. \ref pbdrv is meant for use within
+applications that handle puzzle bus messages, but are not puzzle modules
+themselves. For a complete puzzle module driver, please see \ref pbdrv-mod.
+
+If you order to use \ref pbdrv, you need to include this folder in your
+CMakeLists.txt file, include the \ref pb_ext "extension" for your target
+platform, and link the \c pbdrv library with your executable.
+
+\par Example
+```cmake
+# include pbdrv
+add_subdirectory(lib/pbdrv)
+
+# <use extension>
+
+# link with executable
+target_link_libraries(main pbdrv)
+```
+
+
+\defgroup pbdrv-mod pbdrv-mod
+\brief Puzzle module driver (superset of \ref pbdrv)
+
+pbdrv-mod is a superset of \ref pbdrv, and includes functions specific to
+puzzle bus modules. \ref pbdrv-mod compiles to an object file instead of a
+static library because it may depend on functions that rely on external
+libraries. \ref pbdrv-mod is still considered standalone, but requires either
+using an existing \ref pb_drv "driver", or (partially) implementing the driver
+functions.
+
+Like \ref pbdrv, \ref pbdrv-mod can be used by including this folder in your
+CMakeLists.txt file and linking the library with your executable. Please see
+the \ref pb_drv "drivers" page for target-specific usage instructions.
+
+\par Example
+```cmake
+# include pbdrv
+add_subdirectory(lib/pbdrv)
+
+# link with executable
+target_link_libraries(main pbdrv-mod)
+```
+
+\note In most cases, the \ref pb_hook "hooks" should be sufficient to realize
+extensions or custom behavior not provided by \ref pbdrv-mod.
+
+\note Most \c pb_* functions have a weak implementation, which may be
+overwritten by a custom implementation. This allows you to use the default
+implementation where possible, and only implement extensions required for your
+puzzle module.
+
+\see pbdrv
+
+\{
+
+\defgroup pb_hook Hook
+\brief Functions for (partially) overriding default behavior
+
+Hooks are functions that allow the user to implement custom behavior (i.e.
+extend or conditionally replace the default handlers), without needing to
+completely overwrite the built-in handlers or understand the internals of \ref
+pbdrv-mod.
+
+\}
+
+*/
diff --git a/lib/pbdrv/pb-buf.h b/lib/pbdrv/pb-buf.h
index 78ee380..8b4bb10 100644
--- a/lib/pbdrv/pb-buf.h
+++ b/lib/pbdrv/pb-buf.h
@@ -6,14 +6,30 @@
extern "C" {
#endif
+/**
+ * \ingroup pbdrv
+ * \ingroup pbdrv-mod
+ * \defgroup pb_buf Buffer
+ * \brief Binary data buffer type used in \ref pbdrv
+ * \{
+ */
+
//! binary buffer struct
typedef struct {
- char * data; //! pointer to data
- size_t size; //! size of data
+ char * data; //!< pointer to data
+ size_t size; //!< size of data
} pb_buf_t;
+/**
+ * \brief free a \c pb_buf_t
+ *
+ * This function calls \c pb_free() on the \c data member of a \c pb_buf_t
+ * struct if it is not equal to \c NULL.
+ */
void pb_buf_free(pb_buf_t * buf);
+/// \}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/pbdrv/pb-mem.h b/lib/pbdrv/pb-mem.h
index 72be214..4d0f995 100644
--- a/lib/pbdrv/pb-mem.h
+++ b/lib/pbdrv/pb-mem.h
@@ -6,13 +6,68 @@
extern "C" {
#endif
+/**
+ * \ingroup pbdrv
+ * \ingroup pbdrv-mod
+ * \defgroup pb_mem Memory
+ * \brief Platform-specific memory management functions
+ *
+ * \note This header only declares the memory management functions, and it is
+ * up to \ref pb_ext "extensions" to implement the underlying memory management
+ * functions.
+ *
+ * TODO: ref to extensions
+ *
+ * \{
+ */
+
+/**
+ * \brief Allocate a contiguous chunk of memory
+ * \param sz Requested size of memory area
+ * \return Pointer to memory area, or \c NULL on failure
+ * \note The allocated memory must be free'd again using \c pb_free()
+ */
void * pb_malloc(size_t sz);
+/**
+ * \brief Free a chunk of memory previously allocated with \c pb_malloc()
+ * \param ptr Pointer to memory area
+ */
void pb_free(void * ptr);
+/**
+ * \brief Resize the memory area \c ptr to size \c sz
+ * \param ptr Pointer to allocated memory area
+ * \param sz Requested new size of memory area
+ * \return Pointer to memory area, or \c NULL on failure
+ * \warning This function is not available on FreeRTOS, and should be avoided
+ * if possible. MPack's \c mpack_writer_init_growable() is known to use \c
+ * realloc(), and should not be used for this reason.
+ */
void * pb_realloc(void * ptr, size_t sz);
+/**
+ * \brief copy a memory region
+ * \param dest Pointer to destination memory
+ * \param src Pointer to source memory
+ * \param sz Number of bytes to copy
+ * \return Pointer to \c dest
+ *
+ * This function has a portable implementation, and is always available.
+ */
void * pb_memcpy(void * dest, const void * src, size_t sz);
+/**
+ * \brief compare two memory regions
+ * \param a Pointer to first memory region
+ * \param b Pointer to second memory region
+ * \param sz Number of bytes to compare
+ * \return 0 if the memory regions are identical, or the difference between the
+ * first non-matching byte
+ *
+ * This function has a portable implementation, and is always available.
+ */
int pb_memcmp(const void * a, const void * b, size_t sz);
+/// \}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/pbdrv/pb-mod.h b/lib/pbdrv/pb-mod.h
index ae36d22..91e1d1f 100644
--- a/lib/pbdrv/pb-mod.h
+++ b/lib/pbdrv/pb-mod.h
@@ -1,38 +1,100 @@
#pragma once
-/**
- * \file puzzle bus driver implementation
- *
- * Most \c pb_* functions have a weak implementation, which may be
- * overwritten by a custom implementation. This allows you to use the default
- * implementation where possible, and only implement extensions required for
- * your puzzle module. Please see spec.adoc for more information about how to
- * use the puzzle bus driver library.
- */
-
#include "pb-types.h"
#ifdef __cplusplus
extern "C" {
#endif
-//! puzzle module name (optional, default = "???")
+/**
+ * \ingroup pbdrv-mod
+ * \defgroup pb_mod Module
+ * \brief Puzzle module metadata and auxiliary utility functions
+ * \{
+ */
+
+/**
+ * \brief Puzzle module name
+ * \note This constant is optional to define, its default value is "???"
+ */
extern const char * PB_MOD_NAME;
-//! puzzle module bus address (required)
+/**
+ * \brief Puzzle module bus address
+ * \warning This variable **must** be defined by the user
+ */
extern const i2c_addr_t PB_MOD_ADDR;
+/// \}
+
+/**
+ * \ingroup pbdrv-mod
+ * \defgroup pb_i2c I2C
+ * \brief I2C send/receive handlers
+ *
+ * \{
+ */
+
+/**
+ * \brief Handle a received message from the I2C bus (puzzle bus)
+ *
+ * This function attempts to parse an I2C message as a puzzle bus message, and
+ * calls the appropriate handler for the message if it is considered valid.
+ * Invalid messages are silently ignored.
+ *
+ * \param buf pointer to message content
+ * \param sz size of \p buf
+ *
+ * \note This function should not be directly called from an ISR. Please use
+ * FreeRTOS's \c xTimerPendFunctionCallFromISR() or a similar scheduler-based
+ * deferred function call mechanism instead.
+ */
void pb_i2c_recv(const uint8_t * buf, size_t sz);
+/**
+ * \brief Send a message in master-mode on the I2C bus (puzzle bus)
+ *
+ * This function sends an I2C message to the address specified by \p i2c_addr.
+ *
+ * \param i2c_addr address of slave controller
+ * \param buf pointer to message content
+ * \param sz size of \p buf
+ */
void pb_i2c_send(i2c_addr_t i2c_addr, const uint8_t * buf, size_t sz);
-pb_global_state_t pb_hook_mod_state_read();
-void pb_hook_mod_state_write(pb_global_state_t state);
+/// \}
+
+/// \ingroup pb_hook
+/// \{
/**
- * \brief platform-specific blocking delay function
+ * \defgroup pb_hook_mod_state State
+ * \brief Provide your own global state variable
*
- * FIXME: this should be removed (see handover: RP2040 I2C limitations)
+ * If your puzzle module defines its own global \c pb_global_state_t, you can
+ * tell the driver to use it by implementing these functions. These functions
+ * are also used internally by the driver.
+ *
+ * \{
*/
-void pb_mod_blocking_delay_ms(unsigned long ms);
+
+/**
+ * \brief global state read hook
+ * \return current value of global state enum
+ *
+ * The default implementation of this function uses an internal global state
+ * variable in \ref pbdrv.
+ */
+pb_global_state_t pb_hook_mod_state_read();
+/**
+ * \brief global state write hook
+ * \param state new value of global state enum
+ *
+ * The default implementation of this function uses an internal global state
+ * variable in \ref pbdrv.
+ */
+void pb_hook_mod_state_write(pb_global_state_t state);
+
+/// \}
+/// \}
#ifdef __cplusplus
}
diff --git a/lib/pbdrv/pb-msg.h b/lib/pbdrv/pb-msg.h
index f27d4c4..ff5bcde 100644
--- a/lib/pbdrv/pb-msg.h
+++ b/lib/pbdrv/pb-msg.h
@@ -7,10 +7,53 @@
extern "C" {
#endif
+/**
+ * \ingroup pbdrv
+ * \ingroup pbdrv-mod
+ * \defgroup pb_msg Message
+ * \brief Message (de)serialization
+ * \{
+ */
+
+/**
+ * \brief Serialize a message into a binary buffer
+ *
+ * \note This function allocates a \c pb_buf_t that should be free'd using \c
+ * pb_buf_free()
+ *
+ * \param msg Message to serialize
+ *
+ * \warning The type of \c msg->cmd is inferred from \c msg->type. If the
+ * message is not correctly formatted, this function may cause undefined
+ * behavior. If possible, use functions from \ref pb_send instead.
+ *
+ * \return \c pb_buf_t containing the serialized message, or an empty struct if
+ * serialization failed
+ */
pb_buf_t pb_msg_write(const pb_msg_t * msg);
+/**
+ * \brief Read a binary buffer and attempt to deserialize it as a puzzle bus
+ * message
+ *
+ * \note This function allocates a \c pb_msg_t pointer that should be free'd
+ * using \c pb_msg_free()
+ *
+ * \param buf Binary data to interpret as puzzle bus message
+ *
+ * \return \c pb_msg_t pointer containing the deserialized message, or NULL if
+ * serialization failed
+ */
pb_msg_t * pb_msg_read(const pb_buf_t * buf);
+/**
+ * \brief Recursively free fields of a \c pb_msg_t
+ *
+ * \note The \p msg pointer itself is also free'd by this function. You should
+ * set it to NULL afterwards to avoid confusion.
+ */
void pb_msg_free(pb_msg_t * msg);
+/// \}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/pbdrv/pb-route.c b/lib/pbdrv/pb-route.c
index ee47700..5a7bd67 100644
--- a/lib/pbdrv/pb-route.c
+++ b/lib/pbdrv/pb-route.c
@@ -56,19 +56,27 @@ __weak void pb_route_cmd_prop_req(pb_msg_t * msg) {}
__weak void pb_route_cmd_prop_res(pb_msg_t * msg) {}
__weak void pb_route_cmd_prop_set(pb_msg_t * msg) {}
+//! last known global state of last STATE REQ sender (i.e. main controller)
static pb_global_state_t _main_state = PB_GS_NOINIT;
-__weak void pb_hook_main_state_update(pb_global_state_t state) {}
+__weak void pb_hook_ev_main_state_update(pb_global_state_t state) {}
+__weak void pb_hook_ev_module_init() {
+ pb_hook_mod_state_write(PB_GS_IDLE);
+}
__weak void pb_route_cmd_state_req(pb_msg_t * msg) {
pb_global_state_t own_state = pb_hook_mod_state_read();
- pb_buf_t buf = pb_send_state_res(own_state);
- pb_send_reply(msg, &buf);
- pb_buf_free(&buf);
// notify of new global state variable
pb_cmd_state_t * cmd = msg->cmd;
- if (cmd->state != _main_state)
- pb_hook_main_state_update(cmd->state);
+ if (cmd->state != _main_state) {
+ // first STATE REQ = module init OK
+ if (_main_state == PB_GS_NOINIT) pb_hook_ev_module_init();
+ pb_hook_ev_main_state_update(cmd->state);
+ }
_main_state = cmd->state;
+
+ pb_buf_t buf = pb_send_state_res();
+ pb_send_reply(msg, &buf);
+ pb_buf_free(&buf);
}
__weak void pb_route_cmd_state_res(pb_msg_t * msg) {}
@@ -85,9 +93,6 @@ __weak void pb_route_cmd_magic_req(pb_msg_t * msg) {
// // return early if magic doesn't match
if (pb_memcmp(cmd->magic, pb_cmd_magic_req, sizeof(pb_cmd_magic_req)) != 0) return;
- // FIXME: this should be removed (see handover: RP2040 I2C limitations)
- pb_mod_blocking_delay_ms(2000);
-
pb_buf_t buf = pb_send_magic_res();
pb_send_reply(msg, &buf);
pb_buf_free(&buf);
diff --git a/lib/pbdrv/pb-route.h b/lib/pbdrv/pb-route.h
index 41c009a..2a28c0b 100644
--- a/lib/pbdrv/pb-route.h
+++ b/lib/pbdrv/pb-route.h
@@ -6,31 +6,190 @@
extern "C" {
#endif
-void pb_route_msg(pb_msg_t * msg);
+/**
+ * \ingroup pbdrv-mod
+ * \defgroup pb_route Routing
+ * \internal
+ * \brief Parsed message handler routing
+ *
+ * These functions form a tree-shaped call graph, and are used to handle
+ * specific commands received from \c pb_i2c_recv().
+ *
+ * \{
+ */
-bool pb_hook_route_msg(pb_msg_t * msg);
+/**
+ * \brief Handle a message with type {\ref PB_CMD_PROP "PROP", \ref
+ * PB_CMD_STATE "STATE", \ref PB_CMD_MAGIC "MAGIC"}
+ *
+ * Calls the next handler depending on \c msg->type.
+ */
+void pb_route_msg(pb_msg_t * msg);
+/**
+ * \brief Handle a \ref PB_CMD_PROP "PROP" message with action {\ref
+ * pb_route_cmd_prop_req "REQ", \ref pb_route_cmd_prop_res "RES", \ref
+ * pb_route_cmd_prop_set "SET"}
+ *
+ * Calls the next handler depending on \c msg->action.
+ */
void pb_route_cmd_prop(pb_msg_t * msg);
+/**
+ * \brief Handle a \ref PB_CMD_STATE "STATE" message with action {\ref
+ * pb_route_cmd_state_req "REQ", \ref pb_route_cmd_state_res "RES", \ref
+ * pb_route_cmd_state_set "SET"}
+ *
+ * Calls the next handler depending on \c msg->action.
+ */
void pb_route_cmd_state(pb_msg_t * msg);
+/**
+ * \brief Handle a \ref PB_CMD_MAGIC "MAGIC" message with action {\ref
+ * pb_route_cmd_magic_req "REQ", \ref pb_route_cmd_magic_res "RES"}
+ *
+ * Calls the next handler depending on \c msg->action.
+ *
+ * \note Messages with type \c MAGIC and action \c SET will be silently
+ * ignored, as there is no such command.
+ */
void pb_route_cmd_magic(pb_msg_t * msg);
-bool pb_hook_route_cmd_prop(pb_msg_t * msg);
-bool pb_hook_route_cmd_state(pb_msg_t * msg);
-bool pb_hook_route_cmd_magic(pb_msg_t * msg);
-
+/**
+ * \brief Handle a \ref PB_CMD_PROP "PROP" message with action \ref
+ * PB_ACTION_REQ "REQ"
+ *
+ * The default implementation of this function is empty, as puzzle module
+ * properties are user-defined.
+ */
void pb_route_cmd_prop_req(pb_msg_t * msg);
+/**
+ * \brief Handle a \ref PB_CMD_PROP "PROP" message with action \ref
+ * PB_ACTION_RES "RES"
+ *
+ * The default implementation of this function is empty, as puzzle module
+ * properties are user-defined.
+ */
void pb_route_cmd_prop_res(pb_msg_t * msg);
+/**
+ * \brief Handle a \ref PB_CMD_PROP "PROP" message with action \ref
+ * PB_ACTION_SET "SET"
+ *
+ * The default implementation of this function is empty, as puzzle module
+ * properties are user-defined.
+ */
void pb_route_cmd_prop_set(pb_msg_t * msg);
+/**
+ * \brief Handle a \ref PB_CMD_STATE "STATE" message with action \ref
+ * PB_ACTION_REQ "REQ"
+ *
+ * The default implementation of this function does the following:
+ * - Call \c pb_hook_ev_module_init() if this is the first received \c STATE \c
+ * REQ command.
+ * - Call \c pb_hook_ev_main_state_update() if the main controller state has
+ * changed.
+ * - Reply with a \c STATE \c RES message.
+ */
void pb_route_cmd_state_req(pb_msg_t * msg);
+/**
+ * \brief Handle a \ref PB_CMD_STATE "STATE" message with action \ref
+ * PB_ACTION_RES "RES"
+ *
+ * The default implementation of this function is empty, as only the main
+ * controller handles this type of command.
+ */
void pb_route_cmd_state_res(pb_msg_t * msg);
+// TODO: add link to pb_route_cmd_state_res handler in main/i2c.c
+/**
+ * \brief Handle a \ref PB_CMD_STATE "STATE" message with action \ref
+ * PB_ACTION_SET "SET"
+ *
+ * The default implementation of this function does the following:
+ * - Write the global state variable using \c pb_hook_mod_state_write().
+ */
void pb_route_cmd_state_set(pb_msg_t * msg);
-void pb_hook_main_state_update(pb_global_state_t state);
-
+/**
+ * \brief Handle a \ref PB_CMD_MAGIC "MAGIC" message with action \ref
+ * PB_ACTION_REQ "REQ"
+ *
+ * The default implementation of this function does the following:
+ * - Verify the size of the magic string
+ * - Verify the content of the magic string
+ * - Reply with a \c MAGIC \c RES message.
+ */
void pb_route_cmd_magic_req(pb_msg_t * msg);
+/**
+ * \brief Handle a \ref PB_CMD_MAGIC "MAGIC" message with action \ref
+ * PB_ACTION_RES "RES"
+ *
+ * The default implementation of this function is empty, as only the main
+ * controller handles this type of command. (\ref main_route_cmd_magic_res
+ * "link")
+ */
void pb_route_cmd_magic_res(pb_msg_t * msg);
+/// \}
+
+/**
+ * \ingroup pb_hook
+ * \defgroup pb_hook_route Routing
+ * \brief Conditionally use substitute or extend the built-in message handlers
+ * \{
+ */
+
+/**
+ * \brief \c pb_route_msg() hook
+ *
+ * The default implementation of this function immediately returns false.
+ *
+ * \return \c true if execution should continue to the default handler, or \c
+ * false if it should stop (i.e. the message was handled).
+ */
+bool pb_hook_route_msg(pb_msg_t * msg);
+
+//! \c pb_route_cmd_prop() hook \copydetails pb_hook_route_msg
+bool pb_hook_route_cmd_prop(pb_msg_t * msg);
+//! \c pb_route_cmd_state() hook \copydetails pb_hook_route_msg
+bool pb_hook_route_cmd_state(pb_msg_t * msg);
+//! \c pb_route_cmd_magic() hook \copydetails pb_hook_route_msg
+bool pb_hook_route_cmd_magic(pb_msg_t * msg);
+
+/// \}
+
+/**
+ * \ingroup pb_hook
+ * \defgroup pb_hook_ev Events
+ * \brief Functions called on puzzle bus-related events
+ * \{
+ */
+
+/**
+ * \brief Main controller state update hook
+ *
+ * The default implementation of this function is empty.
+ *
+ * \param state New state of main controller
+ *
+ * \note This function is also called when the first \c STATE \c REQ command is
+ * received, as the main controller state variable used to check if the state
+ * actually changed is initialized to \ref PB_GS_NOINIT. In this case, this
+ * function is called *after* \c pb_hook_ev_module_init().
+ */
+void pb_hook_ev_main_state_update(pb_global_state_t state);
+/**
+ * \brief Module initialized hook
+ *
+ * The default implementation of this function calls \c
+ * pb_hook_mod_state_write() with \ref PB_GS_IDLE.
+ *
+ * This function is called when the first \c STATE \c REQ command is received,
+ * indicating this puzzle module has been registered successfully by the main
+ * controller, and is now part of an active play session.
+ */
+void pb_hook_ev_module_init();
+
+/// \}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/pbdrv/pb-send.c b/lib/pbdrv/pb-send.c
index 66c43c1..dc34c44 100644
--- a/lib/pbdrv/pb-send.c
+++ b/lib/pbdrv/pb-send.c
@@ -2,7 +2,7 @@
#include "pb-mod.h"
#include "pb-msg.h"
-__weak void pb_send_reply(pb_msg_t * msg, pb_buf_t * reply) {
+__weak void pb_send_reply(const pb_msg_t * msg, const pb_buf_t * reply) {
return pb_i2c_send(msg->sender, (uint8_t *) reply->data, reply->size);
}
@@ -21,10 +21,10 @@ pb_buf_t pb_send_read_req(uint8_t propid) {
return pb_msg_write(&msg);
}
-pb_buf_t pb_send_read_res(uint8_t propid, uint8_t * value, size_t size) {
+pb_buf_t pb_send_read_res(uint8_t propid, const uint8_t * value, size_t size) {
pb_cmd_prop_t cmd = {
.propid = propid,
- .value = value,
+ .value = (uint8_t *) value,
._value_size = size,
};
pb_msg_t msg = {
@@ -36,10 +36,10 @@ pb_buf_t pb_send_read_res(uint8_t propid, uint8_t * value, size_t size) {
return pb_msg_write(&msg);
}
-pb_buf_t pb_send_write_req(uint8_t propid, uint8_t * value, size_t size) {
+pb_buf_t pb_send_write_req(uint8_t propid, const uint8_t * value, size_t size) {
pb_cmd_prop_t cmd = {
.propid = propid,
- .value = value,
+ .value = (uint8_t *) value,
._value_size = size,
};
pb_msg_t msg = {
@@ -64,9 +64,9 @@ pb_buf_t pb_send_state_req() {
return pb_msg_write(&msg);
}
-pb_buf_t pb_send_state_res(pb_global_state_t state) {
+pb_buf_t pb_send_state_res() {
pb_cmd_state_t cmd = {
- .state = state,
+ .state = pb_hook_mod_state_read(),
};
pb_msg_t msg = {
.type = PB_CMD_STATE,
diff --git a/lib/pbdrv/pb-send.h b/lib/pbdrv/pb-send.h
index 2f8be1e..7e21eda 100644
--- a/lib/pbdrv/pb-send.h
+++ b/lib/pbdrv/pb-send.h
@@ -7,17 +7,126 @@
extern "C" {
#endif
-void pb_send_reply(pb_msg_t * msg, pb_buf_t * reply);
+/**
+ * \ingroup pbdrv-mod
+ * \defgroup pb_send Send
+ * \brief Functions for directly creating serialized message buffers
+ * \{
+ */
+/**
+ * \brief Utility function for replying to a message
+ *
+ * \param msg Message to reply to
+ * \param reply Data to send as reply
+ *
+ * This function uses \c pb_i2c_send() to send \p reply to \p msg->sender.
+ */
+void pb_send_reply(const pb_msg_t * msg, const pb_buf_t * reply);
+
+/**
+ * \brief Create a serialized \ref PB_CMD_PROP "PROP" \ref PB_ACTION_REQ "REQ"
+ * message
+ *
+ * \param propid Property ID to request
+ *
+ * \return Message buffer
+ *
+ * \note The buffer returned by this function must be free'd with \c
+ * pb_buf_free().
+ */
pb_buf_t pb_send_read_req(uint8_t propid);
-pb_buf_t pb_send_read_res(uint8_t propid, uint8_t * value, size_t size);
-pb_buf_t pb_send_write_req(uint8_t propid, uint8_t * value, size_t size);
+/**
+ * \brief Create a serialized \ref PB_CMD_PROP "PROP" \ref PB_ACTION_RES "RES"
+ * message
+ *
+ * \param propid Requested property ID
+ * \param value Pointer to structured data in property
+ * \param size Size of \p value
+ *
+ * \return Message buffer
+ *
+ * \note The buffer returned by this function must be free'd with \c
+ * pb_buf_free().
+ */
+pb_buf_t pb_send_read_res(uint8_t propid, const uint8_t * value, size_t size);
+/**
+ * \brief Create a serialized \ref PB_CMD_PROP "PROP" \ref PB_ACTION_SET "SET"
+ * message
+ *
+ * \param propid Property ID to write
+ * \param value Pointer to data to write to property
+ * \param size Size of \p value
+ *
+ * \return Message buffer
+ *
+ * \note The buffer returned by this function must be free'd with \c
+ * pb_buf_free().
+ */
+pb_buf_t pb_send_write_req(uint8_t propid, const uint8_t * value, size_t size);
+/**
+ * \brief Create a serialized \ref PB_CMD_STATE "STATE" \ref PB_ACTION_REQ
+ * "REQ" message
+ *
+ * The current module's state is obtained using \c pb_hook_mod_state_read().
+ *
+ * \return Message buffer
+ *
+ * \note The buffer returned by this function must be free'd with \c
+ * pb_buf_free().
+ */
pb_buf_t pb_send_state_req();
-pb_buf_t pb_send_state_res(pb_global_state_t state);
+/**
+ * \brief Create a serialized \ref PB_CMD_STATE "STATE" \ref PB_ACTION_RES
+ * "RES" message
+ *
+ * The current module's state is obtained using \c pb_hook_mod_state_read().
+ *
+ * \return Message buffer
+ *
+ * \note The buffer returned by this function must be free'd with \c
+ * pb_buf_free().
+ */
+pb_buf_t pb_send_state_res();
+/**
+ * \brief Create a serialized \ref PB_CMD_STATE "STATE" \ref PB_ACTION_SET
+ * "SET" message
+ *
+ * \param state Requested new state
+ *
+ * \return Message buffer
+ *
+ * \note The buffer returned by this function must be free'd with \c
+ * pb_buf_free().
+ */
pb_buf_t pb_send_state_set(pb_global_state_t state);
+/**
+ * \brief Create a serialized \ref PB_CMD_MAGIC "MAGIC" \ref PB_ACTION_REQ
+ * "REQ" message
+ *
+ * The magic string is equal to \ref pb_cmd_magic_req.
+ *
+ * \return Message buffer
+ *
+ * \note The buffer returned by this function must be free'd with \c
+ * pb_buf_free().
+ */
pb_buf_t pb_send_magic_req();
+/**
+ * \brief Create a serialized \ref PB_CMD_MAGIC "MAGIC" \ref PB_ACTION_RES
+ * "RES" message
+ *
+ * The magic string is equal to \ref pb_cmd_magic_res.
+ *
+ * \return Message buffer
+ *
+ * \note The buffer returned by this function must be free'd with \c
+ * pb_buf_free().
+ */
pb_buf_t pb_send_magic_res();
+/// \}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/pbdrv/pb-serial.h b/lib/pbdrv/pb-serial.h
index d3d0007..79f08d7 100644
--- a/lib/pbdrv/pb-serial.h
+++ b/lib/pbdrv/pb-serial.h
@@ -8,23 +8,77 @@
extern "C" {
#endif
-#define __pb_cmd(name) \
- pb_ser_r_t pb_ser_r_##name; \
- pb_ser_w_t pb_ser_w_##name; \
- pb_ser_free_t pb_ser_free_##name;
+/**
+ * \ingroup pbdrv
+ * \ingroup pbdrv-mod
+ * \defgroup pb_ser Serial
+ * \internal
+ * \brief Internal (de)serialization functions using mpack
+ *
+ * \{
+ */
+/**
+ * \brief Write (serialize) message fields using mpack
+ *
+ * \param writer Pointer to \c mpack_writer_t instance
+ * \param msg Pointer to message struct to read from
+ */
typedef void pb_ser_w_t(mpack_writer_t * writer, const pb_msg_t * msg);
-pb_ser_w_t pb_ser_w;
-
+/**
+ * \brief Read (deserialize) message fields using mpack
+ *
+ * \param reader Pointer to \c mpack_reader_t instance
+ * \param msg Pointer to message struct to write to
+ */
typedef void pb_ser_r_t(mpack_reader_t * reader, pb_msg_t * msg);
-pb_ser_r_t pb_ser_r;
-
+/**
+ * \brief Recursively free message struct fields
+ *
+ * \param msg Pointer to message struct to free
+ */
typedef void pb_ser_free_t(pb_msg_t * msg);
+
+/**
+ * \brief Write the \ref pb_msg_t header fields and call another function for
+ * \p msg->cmd.
+ * \see pb_ser_w_t
+ */
+pb_ser_w_t pb_ser_w;
+/**
+ * \brief Read the \ref pb_msg_t header fields and call another function for \p
+ * msg->cmd.
+ * \see pb_ser_r_t
+ */
+pb_ser_r_t pb_ser_r;
+/**
+ * \brief Call another function for \p msg->cmd.
+ * \see pb_ser_free_t
+ */
pb_ser_free_t pb_ser_free;
-__pb_cmd(cmd_prop)
-__pb_cmd(cmd_state)
-__pb_cmd(cmd_magic)
+//! Write the \ref pb_cmd_prop_t fields \see pb_ser_w_t
+pb_ser_w_t pb_ser_w_cmd_prop;
+//! Read the \ref pb_cmd_prop_t fields \see pb_ser_r_t
+pb_ser_r_t pb_ser_r_cmd_prop;
+//! Free the \ref pb_cmd_prop_t fields \see pb_ser_free_t
+pb_ser_free_t pb_ser_free_cmd_prop;
+
+//! Write the \ref pb_cmd_state_t fields \see pb_ser_w_t
+pb_ser_w_t pb_ser_w_cmd_state;
+//! Read the \ref pb_cmd_state_t fields \see pb_ser_r_t
+pb_ser_r_t pb_ser_r_cmd_state;
+//! Free the \ref pb_cmd_state_t fields \see pb_ser_free_t
+pb_ser_free_t pb_ser_free_cmd_state;
+
+//! Write the \ref pb_cmd_magic_t fields \see pb_ser_w_t
+pb_ser_w_t pb_ser_w_cmd_magic;
+//! Read the \ref pb_cmd_magic_t fields \see pb_ser_r_t
+pb_ser_r_t pb_ser_r_cmd_magic;
+//! Free the \ref pb_cmd_magic_t fields \see pb_ser_free_t
+pb_ser_free_t pb_ser_free_cmd_magic;
+
+/// \}
#ifdef __cplusplus
}
diff --git a/lib/pbdrv/pb-types.h b/lib/pbdrv/pb-types.h
index 861fa85..44b590b 100644
--- a/lib/pbdrv/pb-types.h
+++ b/lib/pbdrv/pb-types.h
@@ -8,63 +8,125 @@
extern "C" {
#endif
+/**
+ * \ingroup pbdrv
+ * \ingroup pbdrv-mod
+ * \defgroup pb_types Types
+ * \brief Datatypes used within \ref pbdrv
+ *
+ * \{
+ */
+
#ifdef __GNUC__
#define __weak __attribute__((weak))
#endif
#ifndef __weak
#error Could not determine weak attribute for current compiler
+//! Mark function as weak (allow user to override implementation)
#define __weak
#endif
//! I2C address (10 or 7 bit)
typedef uint16_t i2c_addr_t;
-//! puzzle bus command types
-enum pb_cmd_id {
- PB_CMD_PROP, //!< puzzle module property
- PB_CMD_STATE, //!< global state
- PB_CMD_MAGIC, //!< magic (handshake)
-};
-typedef enum pb_cmd_id pb_cmd_id_t;
+//! Puzzle bus command types
+typedef enum {
+ /**
+ * \brief puzzle module property (\ref pb_route_cmd_prop_req "REQ", \ref
+ * pb_route_cmd_prop_res "RES", \ref pb_route_cmd_prop_set "SET")
+ *
+ * The \c PROP command type is used for exchanging arbitrary data between
+ * puzzle modules and/or the puzzle box client (pbc) over the TCP bridge.
+ * These properties are not used by the puzzle framework.
+ */
+ PB_CMD_PROP,
+ /**
+ * \brief puzzle module global state variable (\ref pb_route_cmd_state_req
+ * "REQ", \ref pb_route_cmd_state_res "RES", \ref pb_route_cmd_state_set
+ * "SET")
+ *
+ * The \c STATE command is used by puzzle modules to inform the main
+ * controller about their global state. The main controller aggregates the
+ * states of all connected puzzle modules and exchanges this aggregated state
+ * with the puzzle modules to indicate when the entire puzzle box is solved.
+ */
+ PB_CMD_STATE,
+ /**
+ * \brief magic (handshake) (\ref pb_route_cmd_magic_req "REQ", \ref
+ * pb_route_cmd_magic_res "RES")
+ *
+ * The \c MAGIC command effectively serves as a 'secret handshake' (using a
+ * _magic_ value) which is used to distinguish between puzzle modules and
+ * unrelated I2C devices.
+ */
+ PB_CMD_MAGIC,
+} pb_cmd_id_t;
-//! puzzle bus command action types
-enum pb_action {
+//! Puzzle bus command action types
+typedef enum {
PB_ACTION_REQ, //!< request
PB_ACTION_RES, //!< response
PB_ACTION_SET, //!< (over)write
-};
-typedef enum pb_action pb_action_t;
+} pb_action_t;
-//! puzzle bus global states
-enum pb_global_state {
+//! Puzzle module global states
+typedef enum {
PB_GS_NOINIT, //!< uninitialized (only used by puzzle modules)
PB_GS_IDLE, //!< puzzle not started yet
PB_GS_PLAYING, //!< puzzle actively being solved
PB_GS_SOLVED, //!< puzzle completed
-};
-typedef enum pb_global_state pb_global_state_t;
+} pb_global_state_t;
-//! magic sent from main controller to puzzle module
+/**
+ * \brief Magic sent from main controller to puzzle module (="puzbus")
+ *
+ * The size of this array can be obtained by \c sizeof(pb_cmd_magic_req).
+ */
static const char pb_cmd_magic_req[] = { 0x70, 0x75, 0x7a, 0x62, 0x75, 0x73 };
-//! magic reply from puzzle module back to main controller
+/**
+ * \brief Magic reply from puzzle module back to main controller (="gaming")
+ *
+ * The size of this array can be obtained by \c sizeof(pb_cmd_magic_res).
+ */
static const char pb_cmd_magic_res[] = { 0x67, 0x61, 0x6d, 0x69, 0x6e, 0x67 };
-//! puzzle bus message header (shared by all commands)
+//! puzzle bus message header / container (shared by all commands)
typedef struct {
- pb_cmd_id_t type; //!< command type
- pb_action_t action; //!< command action
- i2c_addr_t sender; //!< i2c address of sender
- void * cmd; //!< command data (type dependant)
+ /**
+ * \brief Command type (see \ref pb_cmd_id_t)
+ *
+ * This is used to identify what the message is about.
+ */
+ pb_cmd_id_t type;
+ /**
+ * \brief Command action (see \ref pb_action_t)
+ *
+ * This is used to specify what should happen as a result of this message.
+ */
+ pb_action_t action;
+ /**
+ * \brief I2C address of sender
+ *
+ * This is used to facilitate the 'network' features, as the sender of an I2C
+ * write is unknown.
+ */
+ i2c_addr_t sender;
+ /**
+ * \brief Command data (dependent on \p type)
+ *
+ * Struct containing command type-specific data.
+ */
+ void * cmd;
} pb_msg_t;
-//! PB_CMD_PROP data
+//! \ref PB_CMD_PROP data
typedef struct {
uint8_t propid; //!< id of state property
uint8_t * value; //!< new or current value
- size_t _value_size; //!< [META] size of \p value
+ size_t _value_size; //!< size of \p value
} pb_cmd_prop_t;
-//! PB_CMD_STATE data
+//! \ref PB_CMD_STATE data
typedef struct {
pb_global_state_t state; //!< global state
} pb_cmd_state_t;
@@ -75,12 +137,14 @@ typedef struct {
pb_global_state_t state; //!< global state
} pb_puzzle_module_t;
-//! PB_CMD_MAGIC data
+//! \ref PB_CMD_MAGIC data
typedef struct {
char * magic; //!< magic value
- size_t _magic_size; //!< [META] size of \p magic
+ size_t _magic_size; //!< size of \p magic
} pb_cmd_magic_t;
+/// \}
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/pbdrv/pb.h b/lib/pbdrv/pb.h
index 0f2e9d1..cef04d8 100644
--- a/lib/pbdrv/pb.h
+++ b/lib/pbdrv/pb.h
@@ -1,23 +1,43 @@
#pragma once
+/**
+ * \ingroup pbdrv
+ * \ingroup pbdrv-mod
+ * \defgroup pb Bus
+ * \brief Constants for the puzzle bus hardware
+ * \{
+ */
+
+//! I2C bus speed in hertz (100 KHz)
#define PB_CLOCK_SPEED_HZ 100000
+//! I2C bus timeout delay in milliseconds
#define PB_TIMEOUT_MS 10
+//! I2C bus timeout delay in microseconds
#define PB_TIMEOUT_US (1e3 * PB_TIMEOUT_MS)
-// Adafruit NeoTrellis modules
+//! Adafruit NeoTrellis module 1 I2C address
#define PB_ADDR_ADA_NEO_1 0x2E
+//! Adafruit NeoTrellis module 2 I2C address
#define PB_ADDR_ADA_NEO_2 0x2F
+//! Adafruit NeoTrellis module 3 I2C address
#define PB_ADDR_ADA_NEO_3 0x30
+//! Adafruit NeoTrellis module 4 I2C address
#define PB_ADDR_ADA_NEO_4 0x32
-// Main controller
+//! Main controller I2C address
#define PB_ADDR_MOD_MAIN 0x08
-// Puzzle modules
+//! NeoTrellis puzzle module I2C address
#define PB_ADDR_MOD_NEOTRELLIS 0x21
+//! Software puzzle module I2C address
#define PB_ADDR_MOD_SOFTWARE 0x22
+//! Hardware puzzle module I2C address
#define PB_ADDR_MOD_HARDWARE 0x23
+//! Vault puzzle module I2C address
#define PB_ADDR_MOD_VAULT 0x24
-// #define BUSADDR_MOD_AUTOMATION 0x25
+//! Automation puzzle module I2C address
+#define BUSADDR_MOD_AUTOMATION 0x25
+//! Dummy puzzle module I2C address
#define PB_ADDR_MOD_DUMMY 0x69
+/// \}
diff --git a/lib/pbdrv/spec.adoc b/lib/pbdrv/spec.adoc
deleted file mode 100644
index 3172e84..0000000
--- a/lib/pbdrv/spec.adoc
+++ /dev/null
@@ -1,133 +0,0 @@
-= Puzzle module specification
-
-This folder contains an implementation of the puzzle bus protocol
-specification, and is targeted at puzzle module developers. This document
-describes the required implementation steps for integrating a new game into the
-puzzle module framework.
-
-== The bus
-
-The puzzle bus carries data over a standard I^2^C bus. Additional details about
-this bus can be found in the link:../../docs/design.adoc[Design document].
-
-The following details are important to puzzle module developers, as they may
-cause unexpected behavior:
-
-- *Addresses influence the puzzle box's behavior*. The order of puzzles is
- determined by the puzzle module address. Two puzzle modules may use the same
- address, but this will mean that they cannot be used simultaniously in the
- same puzzle box. Known addresses are documented in link:bus.h[].
-- *The read/write bit of an I^2^C frame determines how it's handled*. I^2^C
- *read* frames are treated as requests, while *write* frames are treated as
- responses.
-
-== Puzzle bus driver (pbdrv)
-
-The library in this folder is a partial implementation of the puzzle bus
-specification *for puzzle modules*. Most functions in the driver are marked
-with the 'weak' attribute, which allows you to override them by providing an
-implementation.
-
-In order to utilize this driver, the following must be done:
-
-- The ``pbdrv_i2c_recv`` function must be *called* for every received *I^2^C
- read* frame
-- The ``pbdrv_i2c_send`` function must be *implemented* with the
- platform-specific *I^2^C write* function
-
-This is enough to get the puzzle module registered. You may also want to
-implement some of the following integrations:
-
-- If your game uses the global state variable, you should implement the
- <<sec:state-global,global state hooks>> to point the driver to your own
- global state variable, and be notified of reads/writes to it.
-- If you want to expose additional game state variables over the puzzle bus,
- you should implement the <<sec:state-aux,auxiliary state hooks>>.
-- If you want to implement custom puzzle bus commands, you can implement the
- <<sec:cmd,command hook>>.
-
-All other kinds of integrations/hooks can likely be realized by overriding the
-default implementations, but this is discouraged.
-
-[[sec:state-global]]
-== Global state
-
-If your puzzle module defines its own global ``enum pb_state``, you can tell
-the driver to use it by implementing the ``pbdrv_hook_state_read`` and
-``pbdrv_hook_state_write`` functions. These functions are also used by the
-default implementation of the read/write commands to address 0 (global state).
-
-Example:
-
-```c
-pb_state_t global_state = PB_GS_NOINIT;
-
-pb_state_t pbdrv_hook_mod_state_read() {
- return global_state;
-}
-
-void pbdrv_hook_mod_state_write(pb_state_t state) {
- global_state = state;
-}
-```
-
-[[sec:state-aux]]
-== Auxiliary state
-
-You can expose additional state variables by implementing the
-``pbdrv_hook_read`` and ``pbdrv_hook_write`` functions. These functions should
-return ``true`` for state addresses you want to override.
-
-Example:
-
-```c
-#define CUSTOM_VAR_ADDR 0x01
-uint8_t my_custom_variable = 10;
-
-bool pbdrv_hook_read(uint16_t i2c_addr, uint8_t addr) {
- switch (addr) {
- case CUSTOM_VAR_ADDR: {
- char res[] = { PB_CMD_READ, addr, my_custom_variable };
- pbdrv_i2c_send(i2c_addr, res, sizeof(res));
- break;
- }
- default: return false;
- }
-
- return true;
-}
-
-bool pbdrv_hook_write(uint16_t i2c_addr, uint8_t addr, const char * buf, size_t sz) {
- switch (addr) {
- case CUSTOM_VAR_ADDR: {
- if (sz != 1) return false;
- my_custom_variable = buf[0];
- break;
- }
- default: return false;
- }
-
- return true;
-}
-```
-
-[[sec:cmd]]
-== Custom commands
-
-Similar to the auxiliary state, custom commands can be added by implementing
-the ``pbdrv_hook_cmd`` function, which should return ``true`` for the
-command(s) that you want to overwrite.
-
-Example:
-
-```c
-bool pbdrv_hook_cmd(uint16_t i2c_addr, enum pb_cmd cmd, const char * buf, size_t sz) {
- if (cmd == 0x54) {
- printf("custom command received!\n");
- return true;
- }
-
- return false;
-}
-```
-
diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt
index d6cbf33..76b1244 100644
--- a/main/CMakeLists.txt
+++ b/main/CMakeLists.txt
@@ -10,7 +10,6 @@ include(lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/FreeRTOS_Kernel_impor
add_subdirectory(lib/mpack)
add_subdirectory(lib/i2ctcp)
add_subdirectory(lib/pbdrv)
-include(lib/pbdrv/ext/stdlib/include.cmake) # pico-stdlib is compatible with C stdlib
project(puzzlebox_main C CXX ASM)
@@ -24,7 +23,6 @@ add_executable(main
mod.c
tasks.c
blink.c
- pbdrv.c
)
pico_enable_stdio_usb(main 1)
@@ -34,7 +32,7 @@ pico_add_extra_outputs(main)
# include_directories(lib/pico-sdk/lib/lwip/contrib/ports/freertos/include)
target_include_directories(main PRIVATE .)
-target_link_libraries(main
+target_link_libraries(main PUBLIC
pico_cyw43_arch_lwip_sys_freertos
pico_stdlib
pico_i2c_slave
diff --git a/main/blink.h b/main/blink.h
index 51c5f32..f8262d0 100644
--- a/main/blink.h
+++ b/main/blink.h
@@ -1,4 +1,16 @@
#pragma once
+/**
+ * \ingroup main_tasks
+ * \{
+ */
+
+/**
+ * \brief Status LED blink task
+ *
+ * This task is started after initialization is complete, and blinks the
+ * on-board LED to indicate the Pico has completed initialization successfully.
+ */
void blink_task();
+/// \}
diff --git a/main/config.def.h b/main/config.def.h
index e9503ed..cb6e8b4 100644
--- a/main/config.def.h
+++ b/main/config.def.h
@@ -3,31 +3,69 @@
#include <cyw43_country.h>
/**
+ * \ingroup main
+ * \defgroup main_config Config
+ * \brief Configuration options
+ *
+ * The main controller firmware is configured statically (i.e. through
+ * compile-time defined options). Because the configuration is likely to
+ * contain Wi-Fi credentials, this file is not tracked under version control.
+ *
+ * Before compiling the main controller fimrware, a file (`config.h`) must be
+ * created by the user with the following format:
+ *
+ * ```c
+ * #pragma once
+ *
+ * // define non-default options here
+ *
+ * #include "config.def.h"
+ * ```
+ *
+ * \note `config.def.h` contains preprocessor logic that tries to ensure a
+ * correct configuration. The default configuration has the following settings:
+ * - Wi-Fi is disabled (prints a warning during compilation because it was not
+ * explicitly disabled by the user)
+ * - The TCP server is disabled (due to Wi-Fi being disabled)
+ *
+ * \note The exact default values of each configuration option, and all
+ * available options are listed below.
+ *
+ * \{
+ */
+
+/**
* \name Network (Wi-Fi) configuration
* \{
*/
#ifndef CFG_NET_SSID
-//! network name (SSID)
+/**
+ * \brief Network name (SSID)
+ * \note Not defining \c CFG_NET_SSID will implicitly enable \c CFG_NET_DISABLE
+ */
#define CFG_NET_SSID ""
#ifndef CFG_NET_DISABLE
-//! disable network communication
+/**
+ * \brief Disable network communication completely
+ * \note Enabling this option will implicitly enable \c CFG_SRV_DISABLE
+ */
#define CFG_NET_DISABLE
#warning No SSID defined! Disabling network communication!
#endif
#endif
#ifndef CFG_NET_PASS
-//! network password
+//! Network password
#define CFG_NET_PASS ""
#endif
#ifndef CFG_NET_AUTH
-//! network security type
+//! Network security type
#define CFG_NET_AUTH CYW43_AUTH_OPEN
#endif
#ifndef CFG_NET_CONN_TIMEOUT
-//! max duration (milliseconds) for establishing wifi connection
+//! Max duration (milliseconds) for establishing Wi-Fi connection
#define CFG_NET_CONN_TIMEOUT 10e3
#endif
@@ -36,47 +74,60 @@
#define CFG_NET_COUNTRY CYW43_COUNTRY_WORLDWIDE
#endif
#ifndef CFG_NET_COUNTRY
-//! radio communications country
+//! Radio communications country
#define CFG_NET_COUNTRY CYW43_COUNTRY_NETHERLANDS
#endif
-/** \} */
+/// \}
/**
- * \name i2ctcp server configuration
+ * \name TCP server configuration
* \{
*/
#ifndef CFG_SRV_PORT
-//! i2ctcp server port
+//! TCP server port
#define CFG_SRV_PORT 9191
#endif
-
#ifdef CFG_NET_DISABLE
-//! disable the i2ctcp server
+//! Disable the TCP server
#define CFG_SRV_DISABLE
#endif
-/** \} */
+/// \}
/**
* \name I2C configuration
* \{
*/
-#ifndef CFG_SDA_PIN
-//! I^2^C SDA pin
-#define CFG_SDA_PIN 16
+#ifndef CFG_SDA0_PIN
+//! I2C 0 SDA pin
+#define CFG_SDA0_PIN 16
+#endif
+#ifndef CFG_SCL0_PIN
+//! I2C 0 SCL pin
+#define CFG_SCL0_PIN 17
#endif
-#ifndef CFG_SCL_PIN
-//! I^2^C SCL pin
-#define CFG_SCL_PIN 17
+#ifndef CFG_SDA1_PIN
+//! I2C 1 SDA pin
+#define CFG_SDA1_PIN 18
#endif
-/** \} */
+#ifndef CFG_SCL1_PIN
+//! I2C 1 SCL pin
+#define CFG_SCL1_PIN 19
+#endif
+/// \}
+/**
+ * \name Auxiliary options
+ * \{
+ */
#ifndef CFG_LED_PIN
-//! status LED pin
+//! Status LED pin
#define CFG_LED_PIN CYW43_WL_GPIO_LED_PIN
#endif
-
#ifndef CFG_PB_MOD_MAX
-//! maximum number of simultaniously connected puzzle modules
+//! Maximum number of simultaniously connected puzzle modules
#define CFG_PB_MOD_MAX 8
#endif
+/// \}
+
+/// \}
diff --git a/main/i2c.c b/main/i2c.c
index 87ff204..d37a9b7 100644
--- a/main/i2c.c
+++ b/main/i2c.c
@@ -8,15 +8,31 @@
#include "i2c.h"
#include "pb-mod.h"
-#include "pbdrv.h"
#include "config.h"
#include "pb-buf.h"
#include "pb-send.h"
static pb_global_state_t _global_state = PB_GS_IDLE;
pb_puzzle_module_t modules[CFG_PB_MOD_MAX];
+// stolen from lib/pico-sdk/src/rp2_common/hardware_i2c/i2c.c
+#define i2c_reserved_addr(addr) (((addr) & 0x78) == 0 || ((addr) & 0x78) == 0x78)
size_t modules_size = 0;
+static void bus_scan() {
+ pb_buf_t buf = pb_send_magic_req();
+
+ // check for all 7-bit addresses
+ uint16_t addr_max = 1 << 7;
+ for (uint16_t addr = 0x00; addr < addr_max; addr++) {
+ if (i2c_reserved_addr(addr)) continue;
+ if (addr == PB_MOD_ADDR) continue;
+
+ pb_i2c_send(addr, (uint8_t *) buf.data, buf.size);
+ }
+
+ pb_buf_free(&buf);
+}
+
static void state_exchange() {
@@ -74,19 +90,26 @@ void bus_task() {
// do a scan of the bus
bus_scan();
- // FIXME: this should be removed (see handover: RP2040 I2C limitations)
- // wait for 5 seconds until all handshake responses are received
- pb_mod_blocking_delay_ms(5e3);
-
while(1) {
// send my state to all puzzle modules
state_exchange();
// wait 1 second
- pb_mod_blocking_delay_ms(1e3);
+ vTaskDelay(1e3 / portTICK_PERIOD_MS);
}
}
+/**
+ * \ingroup main_pb_override
+ * \anchor main_route_cmd_magic_res
+ *
+ * This function registers the I2C address of the puzzle module that replied to
+ * the \c MAGIC \c REQ command into a list of "known puzzle modules", which are
+ * then periodically updated during gameplay.
+ *
+ * \note Up to \ref CFG_PB_MOD_MAX puzzle modules can be registered
+ * simultaniously.
+ */
void pb_route_cmd_magic_res(pb_msg_t * msg) {
if (modules_size == CFG_PB_MOD_MAX) return;
pb_puzzle_module_t tmp_module = {msg->sender, PB_GS_NOINIT};
diff --git a/main/i2c.h b/main/i2c.h
index d1173c8..27c0b02 100644
--- a/main/i2c.h
+++ b/main/i2c.h
@@ -1,5 +1,18 @@
#pragma once
-//! looking for slave addresses and requesting updates
+/**
+ * \ingroup main_tasks
+ * \{
+ */
+
+/**
+ * \brief I2C bus activity task
+ *
+ * This function does an initial bus scan for puzzle modules, and then goes
+ * into an infinite loop that periodically polls all puzzle modules for their
+ * global state.
+ */
void bus_task();
+/// \}
+
diff --git a/main/index.dox b/main/index.dox
new file mode 100644
index 0000000..54c5b15
--- /dev/null
+++ b/main/index.dox
@@ -0,0 +1,13 @@
+// vim:ft=doxygen
+/**
+\ingroup main
+\defgroup main_tasks Tasks
+\brief FreeRTOS tasks
+*/
+
+/**
+\ingroup main
+\defgroup main_pb_override Overrides
+\brief Override functions from \ref pbdrv-mod
+*/
+
diff --git a/main/init.c b/main/init.c
index 6d29d19..25fa5e3 100644
--- a/main/init.c
+++ b/main/init.c
@@ -7,7 +7,7 @@
#include "config.h"
#include "init.h"
#include "tasks.h"
-#include "pbdrv.h"
+#include "pb-mod.h"
static void init_stdio() {
stdio_init_all();
@@ -29,11 +29,15 @@ static void init_wifi() {
}
static void init_i2c() {
- gpio_set_function(CFG_SDA_PIN, GPIO_FUNC_I2C);
- gpio_set_function(CFG_SCL_PIN, GPIO_FUNC_I2C);
+ gpio_set_function(CFG_SDA0_PIN, GPIO_FUNC_I2C);
+ gpio_set_function(CFG_SCL0_PIN, GPIO_FUNC_I2C);
+ gpio_set_function(CFG_SDA1_PIN, GPIO_FUNC_I2C);
+ gpio_set_function(CFG_SCL1_PIN, GPIO_FUNC_I2C);
- gpio_pull_up(CFG_SDA_PIN);
- gpio_pull_up(CFG_SCL_PIN);
+ gpio_pull_up(CFG_SDA0_PIN);
+ gpio_pull_up(CFG_SCL0_PIN);
+ gpio_pull_up(CFG_SDA1_PIN);
+ gpio_pull_up(CFG_SCL1_PIN);
pb_setup();
}
diff --git a/main/init.h b/main/init.h
index 73d2773..a24977d 100644
--- a/main/init.h
+++ b/main/init.h
@@ -1,11 +1,17 @@
#pragma once
/**
- * \brief initialize the main controller
+ * \ingroup main
+ * \{
+ */
+
+/**
+ * \brief Initialize the main controller
*
* This function only synchronously initializes the standard input/output (used
- * for `printf` and `panic`), and queues all other types of initialization in
- * the `init` task using FreeRTOS.
+ * for \c printf() and \c panic()), and queues all other types of
+ * initialization in the \c async_init() task using FreeRTOS.
*/
void init();
+/// \}
diff --git a/main/mod.c b/main/mod.c
index 11a1bb7..8650861 100644
--- a/main/mod.c
+++ b/main/mod.c
@@ -1,3 +1,6 @@
+#include <FreeRTOS.h>
+#include <task.h>
+
#include "pb.h"
#include "pb-mod.h"
diff --git a/main/pbdrv.c b/main/pbdrv.c
deleted file mode 100644
index 0624897..0000000
--- a/main/pbdrv.c
+++ /dev/null
@@ -1,95 +0,0 @@
-#include "pb.h"
-
-#include "pb.h"
-#include "pb-types.h"
-#include "pb-mod.h"
-#include "pb-send.h"
-
-#include <hardware/i2c.h>
-#include <hardware/gpio.h>
-#include <pico/i2c_slave.h>
-#include <pico/stdio.h>
-
-#include <FreeRTOS.h>
-#include <stdio.h>
-#include <timers.h>
-
-#define PB_I2C i2c0
-#define BUF_SIZE 256
-#define MSGS_MAX 4
-
-typedef struct {
- uint8_t data[BUF_SIZE];
- size_t size;
-} i2c_msg_buf_t;
-
-static i2c_msg_buf_t msgs[MSGS_MAX];
-static size_t msg_index = 0;
-
-static void async_pb_i2c_recv(void * _msg, uint32_t _) {
- i2c_msg_buf_t * msg = _msg;
- pb_i2c_recv(msg->data, msg->size);
-}
-
-static void msg_complete(i2c_msg_buf_t * msg) {
- // defer pb_i2c_recv call to FreeRTOS scheduler as pb_i2c_recv takes
- // too long to return from an ISR
- xTimerPendFunctionCallFromISR(async_pb_i2c_recv, msg, 0, NULL);
-
- // prepare next message for use
- msg_index = (msg_index + 1) % MSGS_MAX;
- msgs[msg_index].size = 0;
-}
-
-// This function is called from the I2C ISR
-static void recv_event(i2c_inst_t *i2c, i2c_slave_event_t event) {
- i2c_msg_buf_t * msg = &msgs[msg_index];
-
- switch (event) {
- case I2C_SLAVE_RECEIVE: {
- if (msg->size == BUF_SIZE) return;
- msg->data[msg->size++] = i2c_read_byte_raw(PB_I2C);
- break;
- }
- case I2C_SLAVE_FINISH: {
- msg_complete(msg);
- break;
- }
- default: break;
- }
-}
-
-void pb_setup() {
- i2c_init(PB_I2C, PB_CLOCK_SPEED_HZ);
- i2c_slave_init(PB_I2C, PB_MOD_ADDR, &recv_event);
-}
-
-__weak void pb_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) {
- i2c_set_slave_mode(PB_I2C, false, PB_MOD_ADDR);
-
- // false to write stop condition to i2c bus
- i2c_write_timeout_us(PB_I2C, addr, buf, sz, false, PB_TIMEOUT_US);
-
- i2c_set_slave_mode(PB_I2C, true, PB_MOD_ADDR);
-}
-
-void bus_scan() {
- i2c_set_slave_mode(PB_I2C, false, PB_MOD_ADDR);
-
- pb_buf_t buf = pb_send_magic_req();
-
- // check for all 7-bit addresses
- uint16_t addr_max = 1 << 7;
- for (uint16_t addr = 0x00; addr < addr_max; addr++) {
- i2c_write_timeout_us(PB_I2C, addr, (uint8_t *) buf.data, buf.size, false, PB_TIMEOUT_US);
- }
-
- pb_buf_free(&buf);
-
- i2c_set_slave_mode(PB_I2C, true, PB_MOD_ADDR);
-}
-
-void pb_mod_blocking_delay_ms(unsigned long ms) {
- vTaskDelay(ms / portTICK_PERIOD_MS);
-}
-
diff --git a/main/pbdrv.h b/main/pbdrv.h
deleted file mode 100644
index a751000..0000000
--- a/main/pbdrv.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#pragma once
-
-#include "pb-types.h"
-
-/**
- * This is the RP2040 puzzle bus driver. This file is no longer inside
- * lib/pb//rp2040 as it is tightly coupled to both the pico-sdk and
- * freertos functions. I have tried to get FreeRTOS to play nicely with the
- * CMake subproject layout, but the pico-sdk and the rp2040 port of freertos
- * both rely on CMake's import() functionality, which makes using FreeRTOS in a
- * libary context extremely messy.
- *
- * The workaround implemented in this driver was already kind of messy, and a
- * different microcontroller should be used for the main controller instead.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//! puzzle bus driver setup
-void pb_setup();
-
-/**
- * While the RP2040's datasheet claims it supports multi-master configurations
- * by implementing bus arbitration, it does not natively support a mode where
- * it is configured as a (multi-)master with a slave address, such that it can
- * be addressed by other multi-masters. This function includes a hacky
- * workaround that teporarily sets the RP2040 to I2C master mode to send a
- * message, and then restores it back to slave mode.
- *
- * This approach results in some received frames being (partially) dropped in
- * the time period between the invocation of this function and the bus becoming
- * idle (and the message is sent).
- */
-void pb_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz);
-
-/**
- * \brief Scan the bus for I2C slaves, and send handshake messages to ACK-ing
- * slaves.
- *
- * As a result of the RP2040 hardware limitations detailed at the top of this
- * file, this function is also implemented in this file, even through it does
- * not belong to the puzzle bus driver. In order to not miss any handshake
- * responses, the bus should remain busy during the entire scan.
- */
-void bus_scan();
-
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/main/readme.md b/main/readme.md
index 28fcfad..97150eb 100644
--- a/main/readme.md
+++ b/main/readme.md
@@ -1,3 +1,6 @@
+\defgroup main main
+\brief Main controller software
+
# main controller firmware
This directory contains the software for the main controller of the Puzzle Box.
@@ -5,17 +8,7 @@ This directory contains the software for the main controller of the Puzzle Box.
## building
1. make sure the submodules are initialized
-2. create a `config.h` file and define some options (see `config.def.h` for all
- options):
- ```c
- #pragma once
-
- #define CFG_NET_SSID "network name"
- #define CFG_NET_PASS "network password"
- #define CFG_NET_AUTH CYW43_AUTH_WPA2_AES_PSK
-
- #include "config.def.h"
- ```
+2. create a `config.h` file (see \ref main_config "config")
3. use CMake to build
## flashing
diff --git a/main/sock.h b/main/sock.h
index 38fca01..a151973 100644
--- a/main/sock.h
+++ b/main/sock.h
@@ -1,8 +1,17 @@
#pragma once
-#include <stdint.h>
-#include <stddef.h>
+/**
+ * \ingroup main_tasks
+ * \{
+ */
-//! start listening for TCP socket requests
+/**
+ * \brief Listen for TCP socket messages
+ *
+ * This task starts a TCP server that listens for messages using \ref i2ctcp,
+ * and sends any received I2C messages (also using \ref i2ctcp).
+ */
void serve_task();
+/// \}
+
diff --git a/main/tasks.h b/main/tasks.h
index 002f830..ac77a9e 100644
--- a/main/tasks.h
+++ b/main/tasks.h
@@ -1,4 +1,13 @@
#pragma once
+/**
+ * \ingroup main
+ * \{
+ */
+
+/**
+ * \brief Register \ref main_tasks "all tasks" in FreeRTOS
+ */
void init_tasks();
+/// \}
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..2ea1c3d
--- /dev/null
+++ b/makefile
@@ -0,0 +1,13 @@
+all: doxygen
+
+.PHONY: FORCE
+
+doxygen: Doxyfile FORCE
+ doxygen
+
+FMT += $(shell git ls-files '*.h' '*.c' '*.cpp')
+format: FORCE
+ clang-format -i $(FMT)
+# clang tidy doesn't work that well :/
+# clang-tidy --fix-errors $(FMT)
+
diff --git a/puzzle/dummy/CMakeLists.txt b/puzzle/dummy/CMakeLists.txt
index 6acc4c8..7edce2b 100644
--- a/puzzle/dummy/CMakeLists.txt
+++ b/puzzle/dummy/CMakeLists.txt
@@ -11,14 +11,13 @@ add_compile_definitions(DEBUG)
# arduino
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/lib/Arduino-CMake-Toolchain/Arduino-toolchain.cmake)
-# set(ARDUINO_BOARD "Arduino Uno [avr.uno]")
-set(ARDUINO_BOARD "Arduino Mega or Mega 2560 [avr.mega]")
+set(ARDUINO_BOARD "Arduino Uno [avr.uno]")
+# set(ARDUINO_BOARD "Arduino Mega or Mega 2560 [avr.mega]")
-# freertos
+# freertos (used for memory management only)
add_library(freertos_config INTERFACE)
target_include_directories(freertos_config SYSTEM INTERFACE .)
-# set(FREERTOS_PORT GCC_ATMEGA) # Arduino Uno
-set(FREERTOS_PORT GCC_ATMEGA) # Arduino Uno
+set(FREERTOS_PORT GCC_ATMEGA)
set(FREERTOS_HEAP 4)
# used for testing
@@ -29,6 +28,7 @@ set(FREERTOS_HEAP 4)
project(pb_mod_dummy C CXX)
add_subdirectory(lib/pbdrv)
+include(lib/pbdrv/ext/freertos/include.cmake)
add_subdirectory(lib/FreeRTOS-Kernel)
add_executable(main
@@ -36,10 +36,10 @@ add_executable(main
mod.c
)
-target_link_libraries(main
+target_link_libraries(main PUBLIC
pbdrv-mod
)
-target_link_arduino_libraries(main
+target_link_arduino_libraries(main PUBLIC
core
Wire
)
diff --git a/puzzle/dummy/FreeRTOSConfig.h b/puzzle/dummy/FreeRTOSConfig.h
index 1cfdd71..1d98f78 100644
--- a/puzzle/dummy/FreeRTOSConfig.h
+++ b/puzzle/dummy/FreeRTOSConfig.h
@@ -17,8 +17,8 @@
#define configSTACK_DEPTH_TYPE uint16_t
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
-// #define configTOTAL_HEAP_SIZE (1024)
-#define configTOTAL_HEAP_SIZE (7 * 1024)
+#define configTOTAL_HEAP_SIZE (1024)
+// #define configTOTAL_HEAP_SIZE (7 * 1024)
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
diff --git a/puzzle/dummy/index.dox b/puzzle/dummy/index.dox
new file mode 100644
index 0000000..918bf7f
--- /dev/null
+++ b/puzzle/dummy/index.dox
@@ -0,0 +1,9 @@
+// vim:ft=doxygen
+/**
+\ingroup puz
+\defgroup puz_dummy Dummy
+\brief Demo puzzle module
+
+The dummy puzzle module consists of an empty Arduino sketch, and can be used as
+a starting point for developing new puzzle modules.
+*/
diff --git a/puzzle/dummy/makefile b/puzzle/dummy/makefile
index 509d8e3..6b8341b 100644
--- a/puzzle/dummy/makefile
+++ b/puzzle/dummy/makefile
@@ -3,18 +3,6 @@ TARGET = $(BUILD_DIR)/main.elf
include ../../lazy.mk
export SERIAL_PORT ?= /dev/ttyACM0
-flash: upload-main;
-upload-main: $(TARGET)
-
-test: test_a test_b;
-
-test_a:
- $(MAKE) -C . clean
- $(MAKE) -E CMFLAGS+=-D\ CMAKE_CXX_FLAGS=-DTEST_A -C .
- $(MAKE) -E SERIAL_PORT=/dev/ttyACM0 -C . flash
-
-test_b:
- $(MAKE) -C . clean
- $(MAKE) -E CMFLAGS+=-D\ CMAKE_CXX_FLAGS=-DTEST_B -C .
- $(MAKE) -E SERIAL_PORT=/dev/ttyACM1 -C . flash
+flash: upload;
+upload: $(TARGET)
diff --git a/puzzle/neo/CMakeLists.txt b/puzzle/neo/CMakeLists.txt
new file mode 100644
index 0000000..6c45f13
--- /dev/null
+++ b/puzzle/neo/CMakeLists.txt
@@ -0,0 +1,44 @@
+cmake_minimum_required(VERSION 3.29)
+
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
+
+# enable debug features
+set(CMAKE_BUILD_TYPE Debug)
+add_compile_definitions(DEBUG)
+
+# arduino
+set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/lib/Arduino-CMake-Toolchain/Arduino-toolchain.cmake)
+set(ARDUINO_BOARD "Arduino Mega or Mega 2560 [avr.mega]")
+
+# freertos
+add_library(freertos_config INTERFACE)
+target_include_directories(freertos_config SYSTEM INTERFACE .)
+set(FREERTOS_PORT GCC_ATMEGA)
+set(FREERTOS_HEAP 4)
+
+project(pb_mod_neo C CXX)
+
+add_subdirectory(lib/pbdrv)
+add_subdirectory(lib/FreeRTOS-Kernel)
+
+add_executable(main
+ main.cpp
+ mod.c
+ )
+
+target_link_libraries(main PUBLIC
+ pbdrv-mod
+ )
+target_link_arduino_libraries(main PUBLIC
+ core
+ Wire
+ Adafruit_seesaw
+ )
+
+# fugly workaround
+target_link_arduino_libraries(_arduino_lib_Adafruit_seesaw_Library PUBLIC "Adafruit BusIO")
+
+target_enable_arduino_upload(main)
+
diff --git a/puzzle/neo/FreeRTOSConfig.h b/puzzle/neo/FreeRTOSConfig.h
new file mode 100644
index 0000000..c0acc49
--- /dev/null
+++ b/puzzle/neo/FreeRTOSConfig.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#define configUSE_PREEMPTION 1
+#define configUSE_IDLE_HOOK 0
+#define configUSE_TICK_HOOK 0
+#define configMAX_PRIORITIES 32
+#define configMINIMAL_STACK_SIZE ((configSTACK_DEPTH_TYPE) 192)
+#define configUSE_16_BIT_TICKS 1
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_MUTEXES 1
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_APPLICATION_TASK_TAG 0
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configQUEUE_REGISTRY_SIZE 8
+#define configUSE_QUEUE_SETS 0
+#define configUSE_TIME_SLICING 1
+#define configSTACK_DEPTH_TYPE uint16_t
+#define configSUPPORT_STATIC_ALLOCATION 0
+#define configSUPPORT_DYNAMIC_ALLOCATION 1
+// #define configTOTAL_HEAP_SIZE (1024)
+#define configTOTAL_HEAP_SIZE (5 * 1024)
+#define configCHECK_FOR_STACK_OVERFLOW 0
+#define configUSE_MALLOC_FAILED_HOOK 0
+#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
+#define configGENERATE_RUN_TIME_STATS 0
+#define configUSE_TRACE_FACILITY 0
+#define configUSE_STATS_FORMATTING_FUNCTIONS 0
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)
+#define configTIMER_QUEUE_LENGTH 10
+#define configTIMER_TASK_STACK_DEPTH 92
+
+#include <assert.h>
+#define configASSERT(x) assert(x)
+
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_xTaskGetSchedulerState 1
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+#define INCLUDE_uxTaskGetStackHighWaterMark 1
+#define INCLUDE_xTaskGetIdleTaskHandle 1
+#define INCLUDE_eTaskGetState 1
+#define INCLUDE_xTimerPendFunctionCall 1
+#define INCLUDE_xTaskAbortDelay 1
+#define INCLUDE_xTaskGetHandle 1
+#define INCLUDE_xTaskResumeFromISR 1
+#define INCLUDE_xQueueGetMutexHolder 1
+
diff --git a/puzzle/neo/console-neopuzzle/neo.cpp b/puzzle/neo/console-neopuzzle/neo.cpp
deleted file mode 100644
index 56d90f7..0000000
--- a/puzzle/neo/console-neopuzzle/neo.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include <iostream>
-#include <array>
-
-#define MATRIX_SIZE 8
-
-enum NeoState {
- NEO_UNINITIALIZED,
- NEO_PLAYING,
- NEO_SOLVED
-};
-
-// Simulate the 8x8 LED matrix with a 2D array
-std::array<std::array<bool, MATRIX_SIZE>, MATRIX_SIZE> neoMatrix;
-
-NeoState neoState = NEO_UNINITIALIZED;
-
-// Helper function to toggle LEDs if within bounds
-void toggleIfValid(int x, int y) {
- if (x >= 0 && x < MATRIX_SIZE && y >= 0 && y < MATRIX_SIZE) {
- neoMatrix[x][y] = !neoMatrix[x][y];
- }
-}
-
-void initializeNeoMatrix() {
- // The initial pattern from the Appendix A example (assuming red is 'true'/on and white is 'false'/off)
- std::array<std::array<bool, MATRIX_SIZE>, MATRIX_SIZE> initialPattern = {{
- {false, true, false, true, false, true, false, true},
- {true, false, true, false, true, false, true, false},
- {false, true, false, true, false, true, false, true},
- {true, false, true, false, true, false, true, false},
- {false, true, false, true, false, true, false, true},
- {true, false, true, false, true, false, true, false},
- {false, true, false, true, false, true, false, true},
- {true, false, true, false, true, false, true, false}
- }};
-
- for (int i = 0; i < MATRIX_SIZE; i++) {
- for (int j = 0; j < MATRIX_SIZE; j++) {
- neoMatrix[i][j] = initialPattern[i][j];
- }
- }
-
- neoState = NEO_PLAYING;
-}
-
-
-void printNeoMatrix() {
- // Print the matrix state to the console
- for (int i = 0; i < MATRIX_SIZE; i++) {
- for (int j = 0; j < MATRIX_SIZE; j++) {
- std::cout << (neoMatrix[i][j] ? 1 : 0) << " ";
- }
- std::cout << std::endl;
- }
-}
-
-void toggleAdjacentLEDs(int x, int y) {
- // Toggle the LED at (x, y) and adjacent LEDs
- toggleIfValid(x, y); // Center
- toggleIfValid(x - 1, y); // Up
- toggleIfValid(x + 1, y); // Down
- toggleIfValid(x, y - 1); // Left
- toggleIfValid(x, y + 1); // Right
-}
-
-
-bool isNeoPuzzleSolved() {
- for (int i = 0; i < MATRIX_SIZE; i++) {
- for (int j = 0; j < MATRIX_SIZE; j++) {
- if (neoMatrix[i][j]) return false; // If any LED is on, puzzle is not solved
- }
- }
- return true;
-}
-
-/// Integration needed
-int main() {
- initializeNeoMatrix();
- printNeoMatrix();
-
- while (neoState != NEO_SOLVED) {
- int x, y;
- std::cout << "Enter the coordinates of the button pressed (x y): ";
- std::cin >> x >> y;
-
- if (x >= 0 && x < MATRIX_SIZE && y >= 0 && y < MATRIX_SIZE) {
- toggleAdjacentLEDs(x, y);
- printNeoMatrix();
-
- if (isNeoPuzzleSolved()) {
- neoState = NEO_SOLVED;
- std::cout << "The NeoTrellis puzzle is solved!\n";
- }
- } else {
- std::cout << "Invalid coordinates. Please enter values between 0 and " << MATRIX_SIZE - 1 << ".\n";
- }
- }
-
- return 0;
-}
diff --git a/puzzle/neo/index.dox b/puzzle/neo/index.dox
new file mode 100644
index 0000000..87822e0
--- /dev/null
+++ b/puzzle/neo/index.dox
@@ -0,0 +1,14 @@
+// vim:ft=doxygen
+/**
+\ingroup puz
+\defgroup puz_neo Neo
+\brief NeoTrellis puzzle module
+
+\par Setup
+- Use the Arduino IDE library manager to install the "Adafruit seesaw Library"
+ library and its dependencies
+
+\warning There is another library named "Adafruit NeoTrellis M4 Library", this
+is not the right library.
+
+*/
diff --git a/puzzle/neo/lib b/puzzle/neo/lib
new file mode 120000
index 0000000..58677dd
--- /dev/null
+++ b/puzzle/neo/lib
@@ -0,0 +1 @@
+../../lib \ No newline at end of file
diff --git a/puzzle/neo/arduino-neopuzzle/arduino-neopuzzle.ino b/puzzle/neo/main.cpp
index b334677..13a6859 100644
--- a/puzzle/neo/arduino-neopuzzle/arduino-neopuzzle.ino
+++ b/puzzle/neo/main.cpp
@@ -1,3 +1,4 @@
+#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_NeoTrellis.h>
@@ -22,6 +23,45 @@ enum NeoState {
NeoState neoState = NEO_UNINITIALIZED;
+void toggleAdjacentLEDs(int x, int y) {
+ for (int dx = -1; dx <= 1; ++dx) {
+ for (int dy = -1; dy <= 1; ++dy) {
+ if (dx == 0 && dy == 0) continue; // Skip the center button itself
+ int nx = x + dx, ny = y + dy;
+ if (nx >= 0 && nx < MATRIX_SIZE && ny >= 0 && ny < MATRIX_SIZE) {
+ neoMatrix[nx][ny] = !neoMatrix[nx][ny];
+ trellis.setPixelColor(nx * MATRIX_SIZE + ny, neoMatrix[nx][ny] ? LED_COLOR_ON : LED_COLOR_OFF);
+ }
+ }
+ }
+}
+
+
+bool isNeoPuzzleSolved() {
+ for (int i = 0; i < MATRIX_SIZE; i++) {
+ for (int j = 0; j < MATRIX_SIZE; j++) {
+ if (neoMatrix[i][j]) return false; // If any LED is on, puzzle is not solved
+ }
+ }
+ return true;
+}
+
+TrellisCallback buttonCallback(keyEvent evt) {
+ int x = evt.bit.NUM / MATRIX_SIZE;
+ int y = evt.bit.NUM % MATRIX_SIZE;
+
+ if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING) {
+ toggleAdjacentLEDs(x, y);
+ trellis.show();
+ if (isNeoPuzzleSolved()) {
+ neoState = NEO_SOLVED;
+ Serial.println("The NeoTrellis puzzle is solved!");
+ }
+ }
+ return 0;
+}
+
+
void setup() {
Serial.begin(115200);
while (!Serial); // Wait for Serial to be ready
@@ -55,41 +95,4 @@ void setup() {
void loop() {
trellis.read(); // Process button events
delay(20);
-}
-
-TrellisCallback buttonCallback(keyEvent evt) {
- int x = evt.bit.NUM / MATRIX_SIZE;
- int y = evt.bit.NUM % MATRIX_SIZE;
-
- if (evt.bit.EDGE == SEESAW_KEYPAD_EDGE_RISING) {
- toggleAdjacentLEDs(x, y);
- trellis.show();
- if (isNeoPuzzleSolved()) {
- neoState = NEO_SOLVED;
- Serial.println("The NeoTrellis puzzle is solved!");
- }
- }
- return 0;
-}
-
-void toggleAdjacentLEDs(int x, int y) {
- for (int dx = -1; dx <= 1; ++dx) {
- for (int dy = -1; dy <= 1; ++dy) {
- if (dx == 0 && dy == 0) continue; // Skip the center button itself
- int nx = x + dx, ny = y + dy;
- if (nx >= 0 && nx < MATRIX_SIZE && ny >= 0 && ny < MATRIX_SIZE) {
- neoMatrix[nx][ny] = !neoMatrix[nx][ny];
- trellis.setPixelColor(nx * MATRIX_SIZE + ny, neoMatrix[nx][ny] ? LED_COLOR_ON : LED_COLOR_OFF);
- }
- }
- }
-}
-
-bool isNeoPuzzleSolved() {
- for (int i = 0; i < MATRIX_SIZE; i++) {
- for (int j = 0; j < MATRIX_SIZE; j++) {
- if (neoMatrix[i][j]) return false; // If any LED is on, puzzle is not solved
- }
- }
- return true;
-}
+} \ No newline at end of file
diff --git a/puzzle/neo/makefile b/puzzle/neo/makefile
new file mode 100644
index 0000000..26e9157
--- /dev/null
+++ b/puzzle/neo/makefile
@@ -0,0 +1,8 @@
+TARGET = $(BUILD_DIR)/main.elf
+
+include ../../lazy.mk
+
+export SERIAL_PORT ?= /dev/ttyACM0
+flash: upload-main;
+upload-main: $(TARGET)
+
diff --git a/puzzle/neo/mod.c b/puzzle/neo/mod.c
new file mode 100644
index 0000000..7157d22
--- /dev/null
+++ b/puzzle/neo/mod.c
@@ -0,0 +1,6 @@
+#include "pb.h"
+#include "pb-mod.h"
+
+const char * PB_MOD_NAME = "neotrellis";
+const i2c_addr_t PB_MOD_ADDR = PB_ADDR_MOD_NEOTRELLIS;
+
diff --git a/puzzle/readme.md b/puzzle/readme.md
index 59c10b1..1b572ba 100644
--- a/puzzle/readme.md
+++ b/puzzle/readme.md
@@ -1,15 +1,15 @@
-# puzzles
-
-This folder contains the source code for all puzzle modules.
+\defgroup puz puzzle
+\brief Puzzle modules
## Arduino-based puzzle modules
-Because of the poorly designed hardware (21-22) used during development
-(23-24), some puzzle modules ended up being developed using Arduino boards. All
-libraries in this repository use CMake for building (for consistency), which
-also means the Arduino based puzzle modules use CMake. The CMakeLists.txt of
-some puzzles uses the [Arduino-CMake-Toolchain][arduino-cmake]. To build any of
-these subfolders, make sure you have done the following:
+> [!NOTE]
+> Because of the poorly designed hardware (21-22) used during development
+> (23-24), all puzzle modules ended up being developed using Arduino boards.
+
+The Arduino based puzzle modules also use CMake with the
+[Arduino-CMake-Toolchain][arduino-cmake]. To build any of these puzzles, make
+sure you have done the following:
- Install the official Arduino IDE
- Open "Tools" > "Board" > "Board manager"
@@ -17,6 +17,8 @@ these subfolders, make sure you have done the following:
[arduino-cmake]: https://github.com/a9183756-gh/Arduino-CMake-Toolchain
+<!--
+
## ESP-based puzzle modules
### ESP-IDF SDK Setup instructions
@@ -29,3 +31,5 @@ these subfolders, make sure you have done the following:
- [For windows](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/windows-setup.html#get-started-windows-first-steps)
- [For Linux](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html#get-started-linux-macos-first-steps)
+-->
+
diff --git a/puzzle/vault/CMakeLists.txt b/puzzle/vault/CMakeLists.txt
new file mode 100644
index 0000000..bc13c8c
--- /dev/null
+++ b/puzzle/vault/CMakeLists.txt
@@ -0,0 +1,41 @@
+cmake_minimum_required(VERSION 3.29)
+
+set(CMAKE_C_STANDARD 11)
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
+
+# enable debug features
+set(CMAKE_BUILD_TYPE Debug)
+add_compile_definitions(DEBUG)
+
+# arduino
+set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/lib/Arduino-CMake-Toolchain/Arduino-toolchain.cmake)
+set(ARDUINO_BOARD "Arduino Mega or Mega 2560 [avr.mega]")
+
+# freertos
+add_library(freertos_config INTERFACE)
+target_include_directories(freertos_config SYSTEM INTERFACE .)
+set(FREERTOS_PORT GCC_ATMEGA)
+set(FREERTOS_HEAP 4)
+
+project(pb_mod_vault C CXX)
+
+add_subdirectory(lib/pbdrv)
+add_subdirectory(lib/FreeRTOS-Kernel)
+
+add_executable(main
+ main.cpp
+ mod.c
+ )
+
+target_link_libraries(main PUBLIC
+ pbdrv-mod
+ )
+target_link_arduino_libraries(main PUBLIC
+ core
+ Wire
+ TM1637
+ )
+
+target_enable_arduino_upload(main)
+
diff --git a/puzzle/vault/FreeRTOSConfig.h b/puzzle/vault/FreeRTOSConfig.h
new file mode 100644
index 0000000..c0acc49
--- /dev/null
+++ b/puzzle/vault/FreeRTOSConfig.h
@@ -0,0 +1,52 @@
+#pragma once
+
+#define configUSE_PREEMPTION 1
+#define configUSE_IDLE_HOOK 0
+#define configUSE_TICK_HOOK 0
+#define configMAX_PRIORITIES 32
+#define configMINIMAL_STACK_SIZE ((configSTACK_DEPTH_TYPE) 192)
+#define configUSE_16_BIT_TICKS 1
+#define configIDLE_SHOULD_YIELD 1
+#define configUSE_MUTEXES 1
+#define configUSE_RECURSIVE_MUTEXES 1
+#define configUSE_APPLICATION_TASK_TAG 0
+#define configUSE_COUNTING_SEMAPHORES 1
+#define configQUEUE_REGISTRY_SIZE 8
+#define configUSE_QUEUE_SETS 0
+#define configUSE_TIME_SLICING 1
+#define configSTACK_DEPTH_TYPE uint16_t
+#define configSUPPORT_STATIC_ALLOCATION 0
+#define configSUPPORT_DYNAMIC_ALLOCATION 1
+// #define configTOTAL_HEAP_SIZE (1024)
+#define configTOTAL_HEAP_SIZE (5 * 1024)
+#define configCHECK_FOR_STACK_OVERFLOW 0
+#define configUSE_MALLOC_FAILED_HOOK 0
+#define configUSE_DAEMON_TASK_STARTUP_HOOK 0
+#define configGENERATE_RUN_TIME_STATS 0
+#define configUSE_TRACE_FACILITY 0
+#define configUSE_STATS_FORMATTING_FUNCTIONS 0
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)
+#define configTIMER_QUEUE_LENGTH 10
+#define configTIMER_TASK_STACK_DEPTH 92
+
+#include <assert.h>
+#define configASSERT(x) assert(x)
+
+#define INCLUDE_vTaskPrioritySet 1
+#define INCLUDE_uxTaskPriorityGet 1
+#define INCLUDE_vTaskDelete 1
+#define INCLUDE_vTaskSuspend 1
+#define INCLUDE_vTaskDelayUntil 1
+#define INCLUDE_vTaskDelay 1
+#define INCLUDE_xTaskGetSchedulerState 1
+#define INCLUDE_xTaskGetCurrentTaskHandle 1
+#define INCLUDE_uxTaskGetStackHighWaterMark 1
+#define INCLUDE_xTaskGetIdleTaskHandle 1
+#define INCLUDE_eTaskGetState 1
+#define INCLUDE_xTimerPendFunctionCall 1
+#define INCLUDE_xTaskAbortDelay 1
+#define INCLUDE_xTaskGetHandle 1
+#define INCLUDE_xTaskResumeFromISR 1
+#define INCLUDE_xQueueGetMutexHolder 1
+
diff --git a/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino b/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino
deleted file mode 100644
index 4dd8ac8..0000000
--- a/puzzle/vault/arduino-vaultpuzzle/arduino-vaultpuzzle.ino
+++ /dev/null
@@ -1,150 +0,0 @@
-#include <Wire.h>
-#include <TM1637Display.h>
-
-// Definitions for GPIO numbers, change these according to your hardware setup
-#define TOTAL_LEVELS 5
-#define TAG "VaultPuzzle"
-
-// Key Matrix Pin Configuration
-#define ROWS 4
-#define COLS 3
-
-// Module connection pins (Digital Pins for TM1637)
-#define CLK 2
-#define DIO 3
-
-// Pin to indicate puzzle solved state
-#define SOLVED_PIN 53
-
-// Initialize the TM1637 display
-TM1637Display display(CLK, DIO);
-
-//TODO Update these pin numbers based on your Arduino setup
-const int ROW_PINS[ROWS] = {7, 6, 5, 4};
-const int COL_PINS[COLS] = {10, 9, 8};
-
-typedef enum {
- STATE_UNINITIALIZED = 0x00,
- STATE_RESET = 0x01,
- STATE_PLAYING = 0x02,
- STATE_SOLVED = 0x03,
- STATE_ERROR = 0x04
-} PuzzleState;
-
-const char* validButtons[TOTAL_LEVELS] = {"A2", "B1", "D3", "C2", "C1"};
-PuzzleState puzzleState = STATE_UNINITIALIZED;
-int currentLevel = 0;
-
-// Function prototypes
-void display_code(int level);
-void initialize_system();
-void check_button_press();
-void update_state_after_button_press(bool validPress);
-void play_error_sound();
-void blink_display();
-
-void setup() {
- Serial.begin(115200); // Initialize default Serial for debug messages
- pinMode(SOLVED_PIN, OUTPUT); // Initialize the solved indicator pin
- digitalWrite(SOLVED_PIN, LOW); // Start with the solved pin LOW
-
- display.setBrightness(0x0f); // Set the brightness of the TM1637 display
- initialize_system();
- Serial.println("GPIO and display initialized.");
-
- // Test to light up all segments
- uint8_t allOn[] = {0xFF, 0xFF, 0xFF, 0xFF}; // All segments on
- display.setSegments(allOn);
- delay(2000); // Keep it on for 2 seconds before proceeding
-
- // Initialize the game
- if (true) { // Simulating isVaultClosed
- puzzleState = STATE_RESET;
- currentLevel = 0;
- display_code(currentLevel);
- } else {
- Serial.println("Vault door is open. Please close the door to start the puzzle.");
- }
-}
-
-void initialize_system() {
- // Configure the rows as input with pull-up
- for (int i = 0; i < ROWS; i++) {
- pinMode(ROW_PINS[i], INPUT_PULLUP);
- }
-
- // Configure the columns as output
- for (int i = 0; i < COLS; i++) {
- pinMode(COL_PINS[i], OUTPUT);
- digitalWrite(COL_PINS[i], HIGH);
- }
-}
-
-void loop() {
- while (puzzleState != STATE_SOLVED) {
- check_button_press();
- delay(100); // Non-blocking delay
- }
- // When puzzle is solved, you might want to display a final message and set the solved pin high
- if (puzzleState == STATE_SOLVED) {
- digitalWrite(SOLVED_PIN, HIGH); // Set the solved pin high
- display.showNumberDec(currentLevel, true); // Show final level or a special message
- Serial.println("Final display shown. Puzzle complete.");
- while (1) { delay(1000); } // Hold on the final display
- }
-}
-
-void display_code(int level) {
- Serial.print("Displaying code for level "); Serial.println(level);
- // Display the level on the TM1637 4-digit 7-segment display
- display.showNumberDec(level, true); // True to show leading zeros
- Serial.print("Code for level "); Serial.print(level); Serial.println(" displayed successfully.");
-}
-
-void check_button_press() {
- char keyPress[3] = {0};
- for (int col = 0; col < COLS; col++) {
- digitalWrite(COL_PINS[col], LOW); // Activate column
- for (int row = 0; row < ROWS; row++) {
- if (digitalRead(ROW_PINS[row]) == LOW) { // Detect if any row is activated
- delay(50); // Debounce delay
- if (digitalRead(ROW_PINS[row]) == LOW) { // Confirm the button is still pressed
- keyPress[0] = 'A' + row;
- keyPress[1] = '1' + col;
- keyPress[2] = '\0';
- Serial.print("Keypress detected: "); Serial.println(keyPress);
- if (strcmp(keyPress, validButtons[currentLevel]) == 0) {
- currentLevel++;
- if (currentLevel >= TOTAL_LEVELS) {
- puzzleState = STATE_SOLVED;
- Serial.println("Puzzle solved!");
- display.showNumberDec(currentLevel + 1, true); // Display the final level
- digitalWrite(SOLVED_PIN, HIGH); // Set the solved pin high
- } else {
- puzzleState = STATE_PLAYING;
- display_code(currentLevel);
- }
- } else {
- play_error_sound();
- blink_display();
- puzzleState = STATE_ERROR;
- currentLevel = 0;
- display_code(currentLevel);
- }
- while (digitalRead(ROW_PINS[row]) == LOW) {} // Wait for release
- }
- }
- }
- digitalWrite(COL_PINS[col], HIGH); // Deactivate column
- }
-}
-
-void play_error_sound() {
- // Simulate error sound - connect a buzzer to play actual sound
- Serial.println("Playing error sound.");
-}
-
-void blink_display() {
- // Simulate blinking the display - use LEDs or other methods to show visual feedback
- Serial.println("7-segment display is blinking to indicate an error.");
-}
diff --git a/puzzle/vault/console-vaultpuzzle/vault.cpp b/puzzle/vault/console-vaultpuzzle/vault.cpp
deleted file mode 100644
index 3566b3e..0000000
--- a/puzzle/vault/console-vaultpuzzle/vault.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <iostream>
-#include <string>
-#include <array>
-
-// Definitions for puzzle requirements
-constexpr int TOTAL_LEVELS = 5;
-
-// Enumeration for the states of the puzzle
-enum PuzzleState {
- STATE_UNINITIALIZED,
- STATE_RESET,
- STATE_PLAYING,
- STATE_SOLVED,
- STATE_ERROR
-};
-
-// This array maps each level to the correct button press
-const std::array<std::string, TOTAL_LEVELS> validButtons = {"A3", "F1", "U4", "C2", "L1"};
-
-PuzzleState puzzleState = STATE_UNINITIALIZED;
-int currentLevel = 0;
-
-// Function prototypes
-void displayCode(int level);
-void sendI2CUpdate(PuzzleState state);
-
-// Simulate sending an I2C update
-void sendI2CUpdate(PuzzleState state) {
- std::cout << "Sending state " << state << " to main controller via I2C.\n";
-}
-
-// Simulate checking if the vault door is closed
-bool isVaultClosed() {
- return true; // Return true if the door sensor indicates closed
-}
-
-// Function to display a code on the 7-segment display
-void displayCode(int level) {
- std::cout << "Displaying code for level " << level << " on the 7-segment display.\n";
-}
-
-// Function to initialize the puzzle
-void initializePuzzle() {
- if (isVaultClosed()) {
- puzzleState = STATE_RESET;
- currentLevel = 1; // Start at level 1
- std::cout << "Puzzle initialized. Starting at level " << currentLevel << ".\n";
- displayCode(currentLevel); // Show the first code
- } else {
- std::cout << "Vault door is open. Please close the door to start the puzzle.\n";
- }
-}
-
-// Function to lock the vault
-void lockVault() {
- std::cout << "Vault locked.\n";
-}
-
-// Function to unlock the vault
-void unlockVault() {
- std::cout << "Vault unlocked!\n";
-}
-
-// Function to simulate the buzzer sound
-void playErrorSound() {
- std::cout << "Playing error sound.\n";
-}
-
-// Function to simulate blinking the 7-segment display
-void blinkDisplay() {
- std::cout << "7-segment display is blinking to indicate an error.\n";
-}
-
-// Validate the button press for the current level
-bool isValidButtonPress(const std::string& button, int level) {
- return button == validButtons[level - 1];
-}
-
-// Function to update the state of the puzzle based on the current level
-void updateStateAfterButtonPress(bool validPress) {
- if (validPress) {
- if (currentLevel >= TOTAL_LEVELS) {
- puzzleState = STATE_SOLVED;
- unlockVault();
- } else {
- puzzleState = STATE_PLAYING;
- displayCode(currentLevel);
- }
- } else {
- puzzleState = STATE_ERROR;
- playErrorSound();
- blinkDisplay();
- lockVault();
- currentLevel = 1; // Reset to level 1
- displayCode(currentLevel);
- }
- sendI2CUpdate(puzzleState); // Notify main controller of the state change
-}
-
-int main() {
- initializePuzzle();
-
- std::string buttonInput;
-
- while (puzzleState != STATE_SOLVED) {
- std::cout << "Enter the button pressed for level " << currentLevel << " (format Xn, e.g., A3): ";
- std::getline(std::cin, buttonInput);
-
- if (!buttonInput.empty() && isValidButtonPress(buttonInput, currentLevel)) {
- currentLevel++;
- if (currentLevel > TOTAL_LEVELS) {
- puzzleState = STATE_SOLVED;
- unlockVault();
- std::cout << "The puzzle is solved and the vault is open!\n";
- } else {
- displayCode(currentLevel);
- }
- } else {
- playErrorSound();
- blinkDisplay();
- lockVault();
- puzzleState = STATE_RESET;
- currentLevel = 1;
- displayCode(currentLevel);
- }
- sendI2CUpdate(puzzleState);
- }
-
- return 0;
-}
diff --git a/puzzle/vault/index.dox b/puzzle/vault/index.dox
new file mode 100644
index 0000000..15eae1f
--- /dev/null
+++ b/puzzle/vault/index.dox
@@ -0,0 +1,11 @@
+// vim:ft=doxygen
+/**
+\ingroup puz
+\defgroup puz_vault Vault
+\brief Vault puzzle module
+
+\par Setup
+- Use the Arduino IDE library manager to install the "TM1637" library (by
+ Avishay Orpaz) and its dependencies
+
+*/
diff --git a/puzzle/vault/lib b/puzzle/vault/lib
new file mode 120000
index 0000000..58677dd
--- /dev/null
+++ b/puzzle/vault/lib
@@ -0,0 +1 @@
+../../lib \ No newline at end of file
diff --git a/puzzle/vault/main.cpp b/puzzle/vault/main.cpp
new file mode 100644
index 0000000..2e4cafc
--- /dev/null
+++ b/puzzle/vault/main.cpp
@@ -0,0 +1,187 @@
+#include <Arduino.h>
+#include <TM1637Display.h>
+#include "lib/pbdrv/pb-types.h"
+#include "lib/pbdrv/pb-mod.h"
+
+#define TOTAL_LEVELS 5
+#define ROWS 4
+#define COLS 3
+#define CLK 2
+#define DIO 3
+#define SOLVED_PIN 53
+#define I2C_MODULE_ADDRESS 0x08 // Address of the puzzle module
+#define HANDSHAKE_RECEIVED {0x70, 0x75, 0x7a, 0x62, 0x75, 0x73} // Magic command for the handshake
+#define HANDSHAKE_SEND {0x67, 0x61, 0x6d, 0x69, 0x6e, 0x67} // Magic command for the handshake
+#define REQUEST_STATE_CMD 0x53 // 'S' to request the game state
+
+const int ROW_PINS[ROWS] = {7, 6, 5, 4};
+const int COL_PINS[COLS] = {10, 9, 8};
+const char* validButtons[TOTAL_LEVELS] = {"A2", "B1", "D3", "C2", "C3"};
+const char bombCode[] = "1234";
+const uint8_t SEGMENT_MAP[] = {
+ 0b00111111, // 0
+ 0b00000110, // 1
+ 0b01011011, // 2
+ 0b01001111, // 3
+ 0b01100110, // 4
+ 0b01101101, // 5
+ 0b01111101, // 6
+ 0b00000111, // 7
+ 0b01111111, // 8
+ 0b01101111, // 9
+ 0b01110111, // A
+ 0b01111100, // B
+ 0b00111001, // C
+ 0b01011110, // D
+ 0b01111001, // E
+ 0b01110001 // F
+ // Add other letters if needed
+};
+
+// This array of level codes matches the codes you might display per level.
+const char* levelCodes[TOTAL_LEVELS] = {"A1", "B2", "D1", "C3", "A2"};
+
+
+// Puzzle state
+pb_global_state_t puzzleState = PB_GS_NOINIT;
+
+TM1637Display display(CLK, DIO);
+
+int currentLevel = 0;
+
+void blink_display(int num) {
+ if (num == 1) {
+ // Display "1111" with leading zeros shown if necessary
+ display.showNumberDecEx(1111, 0b11111111, true);
+ } else if (num == 0) {
+ // Display "0000" with leading zeros shown if necessary
+ display.showNumberDecEx(0, 0b11111111, true);
+ }
+ delay(500);
+ display.clear();
+ delay(500);
+}
+
+
+void display_final_code(const char* code) {
+ uint8_t segs[4] = {0, 0, 0, 0};
+ int numDigits = strlen(code);
+ numDigits = numDigits > 4 ? 4 : numDigits;
+
+ for (int i = 0; i < numDigits; i++) {
+ segs[i] = display.encodeDigit(code[i] - '0');
+ }
+
+ display.setSegments(segs, numDigits, 0);
+}
+
+void check_button_press() {
+ for (int col = 0; col < COLS; col++) {
+ digitalWrite(COL_PINS[col], LOW);
+ for (int row = 0; row < ROWS; row++) {
+ if (digitalRead(ROW_PINS[row]) == LOW) {
+ delay(50);
+ if (digitalRead(ROW_PINS[row]) == LOW) {
+ char keyPress[3] = {'A' + row, '1' + col, '\0'};
+ Serial.print("Keypress detected: ");
+ Serial.println(keyPress);
+ if (strcmp(keyPress, validButtons[currentLevel]) == 0) {
+ currentLevel++;
+ if (currentLevel >= TOTAL_LEVELS) {
+ pb_hook_mod_state_write(PB_GS_SOLVED);
+ Serial.println("Puzzle solved!");
+ display.showNumberDec(currentLevel + 1, true);
+ digitalWrite(SOLVED_PIN, HIGH);
+ }
+ } else {
+ currentLevel = 0;
+ }
+ while (digitalRead(ROW_PINS[row]) == LOW) {} // Ensure button release
+ }
+ }
+ }
+ digitalWrite(COL_PINS[col], HIGH);
+ }
+}
+
+void initialize_system() {
+ for (int i = 0; i < ROWS; i++) {
+ pinMode(ROW_PINS[i], INPUT_PULLUP);
+ }
+ for (int i = 0; i < COLS; i++) {
+ pinMode(COL_PINS[i], OUTPUT);
+ digitalWrite(COL_PINS[i], HIGH);
+ }
+ Serial.println("GPIO and display initialized.");
+}
+
+void display_code_for_level(int level) {
+ char code[3] = {0}; // Temp storage for level code
+ strncpy(code, levelCodes[level], 2); // Copy the level-specific code
+
+ uint8_t segs[4] = {0}; // Segments to send to the display
+
+ // Check if the first character is a letter and map it
+ if (isalpha(code[0])) {
+ if (code[0] >= 'A' && code[0] <= 'F') {
+ segs[0] = SEGMENT_MAP[code[0] - 'A' + 10]; // Maps A-F to their segment patterns
+ } else {
+ // Handle unexpected characters or extend SEGMENT_MAP for more letters
+ segs[0] = 0; // Display nothing for undefined letters
+ }
+ } else {
+ // Assume it's a number and map directly
+ segs[0] = SEGMENT_MAP[code[0] - '0'];
+ }
+
+ // Check if the second character is a digit and map it
+ if (isdigit(code[1])) {
+ segs[1] = SEGMENT_MAP[code[1] - '0'];
+ } else {
+ // Handle unexpected characters
+ segs[1] = 0; // Display nothing for undefined digits
+ }
+
+ // Set only the first two segments, leave others blank
+ display.setSegments(segs, 2, 0); // Display on leftmost two digits
+}
+
+
+pb_global_state_t pb_hook_mod_state_read() {
+ return puzzleState;
+}
+
+void pb_hook_mod_state_write(pb_global_state_t state) {
+ puzzleState = state;
+}
+
+void setup() {
+ Serial.begin(115200);
+ pinMode(SOLVED_PIN, OUTPUT);
+ digitalWrite(SOLVED_PIN, LOW);
+ display.setBrightness(0x0f);
+ initialize_system();
+}
+
+void loop() {
+ switch(puzzleState) {
+ case PB_GS_PLAYING:
+ display_code_for_level(currentLevel);
+ check_button_press();
+ delay(100);
+ break;
+ case PB_GS_SOLVED:
+ Serial.println("STATE = PB_GS_SOLVED");
+ display_final_code(bombCode);
+ digitalWrite(SOLVED_PIN, HIGH);
+ break;
+ case PB_GS_NOINIT:
+ Serial.println("STATE = PB_GS_NOINIT");
+ blink_display(0);
+ break;
+ case PB_GS_IDLE:
+ Serial.println("STATE = PB_GS_IDLE");
+ blink_display(1);
+ break;
+ }
+} \ No newline at end of file
diff --git a/puzzle/vault/makefile b/puzzle/vault/makefile
new file mode 100644
index 0000000..f33ca7e
--- /dev/null
+++ b/puzzle/vault/makefile
@@ -0,0 +1,8 @@
+TARGET = $(BUILD_DIR)/main.elf
+
+include ../../lazy.mk
+
+export SERIAL_PORT ?= /dev/ttyUSB0
+flash: upload;
+upload: $(TARGET)
+
diff --git a/puzzle/vault/mod.c b/puzzle/vault/mod.c
new file mode 100644
index 0000000..bae8a3d
--- /dev/null
+++ b/puzzle/vault/mod.c
@@ -0,0 +1,6 @@
+#include "pb.h"
+#include "pb-mod.h"
+
+const char * PB_MOD_NAME = "vault";
+const i2c_addr_t PB_MOD_ADDR = PB_ADDR_MOD_VAULT;
+
diff --git a/readme.md b/readme.md
index 457ffaa..5f71788 100644
--- a/readme.md
+++ b/readme.md
@@ -5,45 +5,60 @@ implemented during the 2023-2024 run of the Puzzlebox project. This year's run
of the project consists of only software students, and was developed using the
hardware from the 21-22 run of the project.
-Improved hardware was designed but not realised during the 22-23 run of the
-project. This hardware is recommended for future groups participating in the
-project. The software in this repository should be easily portable to various
-other microcontrollers, and a recommendation is made in the [design
-document](docs/design.adoc).
+The software in this repository should be easily portable to various other
+microcontrollers, and a recommendation is made in the [design
+document](docs/design.adoc). Please see the [handover
+document](docs/handover.adoc) first for more details.
-## Tidyness
+> [!NOTE]
+> This project was mostly developed on Linux. All subfolders/modules/libraries
+> use CMake, and *should* build cross-platform when using CMake+Ninja. This has
+> not yet been verified.
+>
+> Please note that most subfolders use symbolic links to the [lib](lib/)
+> folder, which may not work correctly if you clone the repository under a
+> filesystem or operating system that does not support these.
+
+## Documentation
-Please keep this repository tidy by being aware of the following conventions!
+If you are viewing this page from Doxygen, please take a look at the
+[components](topics.html) tab for a comprehensive list of components within
+this project.
-### Folder structure
+Project documentation is available in the [docs](docs/) folder, and all code is
+documented using Doxygen. To generate HTML docs, run
```
-/client desktop PC application for controlling the puzzle box
-/docs project documentation in AsciiDoc(tor) format
-/lib custom libraries and submodules
-├───/i2ctcp I2C over TCP protocol functions (used by main and client)
-├───/mpack MsgPack CMake configuration and extension
-└───/pbdrv puzzle bus driver (module driver + (de)serializing functions)
-/main main controller (RPi pico) software
-/puzzle/<name> puzzle sources, each puzzle has its own subdirectory
-/shared (unused) shared code
-/test unit tests
+$ make doxygen
```
-### Code style
+and open [the generated HTML files](doxygen/html/index.html) in a browser. A
+rendered copy of this documentation is also hosted unofficially at
+[pipeframe](https://media.pipeframe.xyz/puzzlebox/23-24/doxygen).
+
+## Tidyness
+
+Please keep this repository tidy by being aware of the following conventions:
-An `.editorconfig` file is provided in this repository. Please install the
-[EditorConfig](https://editorconfig.org/) plugin for your text editor of choice
-to automatically use these.
+- An `.editorconfig` file is provided in this repository. Please install the
+ [EditorConfig](https://editorconfig.org/) plugin for your text editor of
+ choice to automatically use these.
+- There are also `.clang-tidy` and `.clang-format` files, which can be enforced
+ by running
-Currently, no linter/formatter is configured for maintaining consistent code
-style.
+ ```
+ $ make format
+ ```
-## Submodules
+## Libraries
-This repository tracks (most) dependencies via git submodules.
+Libraries are stored in the [lib](lib/) folder, and this folder is symlinked to
+from each subfolder in the project for convenience (allows CMake to include
+out-of-tree modules). The lib folder contains a mix of direct Git submodules
+and custom libraries specific to this project. (Most) external dependencies are
+tracked as git submodules, exceptions are in the [puzzle](puzzle/) folder.
-If something is complaining about missing files
+TL;DR: If something is complaining about missing files
```
git submodule update --init --recursive --depth 1