aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doxyfile12
-rw-r--r--client/cmd.h140
-rw-r--r--client/pbc.190
-rw-r--r--client/readme.md23
-rw-r--r--client/rl.cpp7
-rw-r--r--client/sock.h1
-rw-r--r--lib/pbdrv/drv/arduino/mod.cpp6
-rw-r--r--lib/pbdrv/drv/index.dox7
-rw-r--r--lib/pbdrv/index.dox5
-rw-r--r--lib/pbdrv/mod/main/pb-mod-main.h13
-rw-r--r--lib/pbdrv/pb-mod.h24
-rw-r--r--lib/pbdrv/pb-route.h6
-rw-r--r--main/config.def.h2
-rw-r--r--main/i2c.c1
14 files changed, 191 insertions, 146 deletions
diff --git a/Doxyfile b/Doxyfile
index 3dd7951..fccbfdf 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -4,10 +4,15 @@ PROJECT_NAME = "puzzlebox"
OUTPUT_DIRECTORY = doxygen
LAYOUT_FILE = docs/doxygen-layout.xml
+# read these files first (fixes broken links)
INPUT += readme.md
+INPUT += lib/pbdrv/pb-mod.h
+INPUT += client/cmd.h
+
+# find remaining files
+INPUT += lib/pbdrv
INPUT += lib/mpack
INPUT += lib/i2ctcp
-INPUT += lib/pbdrv
INPUT += client
INPUT += main
INPUT += puzzle
@@ -15,6 +20,7 @@ INPUT += puzzle
EXCLUDE = lib/mpack/src
EXCLUDE_PATTERNS = **/build
EXCLUDE_SYMLINKS = YES
+EXCLUDE_SYMBOLS = _*
FILE_PATTERNS = *.c *.cpp *.h *.hpp *.md *.dox
RECURSIVE = YES
@@ -24,10 +30,12 @@ GENERATE_LATEX = NO
ALIASES += I2C="I²C"
INPUT_FILTER = "sed -e 's/\<I2C\>\|\<I<sup>2<\/sup>C\>/\\I2C/g'"
-USE_MDFILE_AS_MAINPAGE = readme.md
+USE_MDFILE_AS_MAINPAGE = ./readme.md
HTML_INDEX_NUM_ENTRIES = 1 # collapse trees by default
REPEAT_BRIEF = NO
INTERNAL_DOCS = YES
EXTRACT_STATIC = YES
+QUIET = YES
+
diff --git a/client/cmd.h b/client/cmd.h
index e2c412a..eac9834 100644
--- a/client/cmd.h
+++ b/client/cmd.h
@@ -5,10 +5,6 @@
* \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.
- *
* \{
*/
@@ -45,13 +41,149 @@ typedef struct {
cmd_complete_t * complete; //!< Completion function (optional = NULL)
} cmd_t;
+/**
+ * \anchor pbc_cmd_usage
+ * \name Command usage
+ * \{
+ */
+
+/**
+ * \brief \c exit command
+ *
+ * ```
+ * (pbc) exit
+ * ```
+ *
+ * Disconnect from the puzzle box and exit \c pbc. This command takes no
+ * arguments.
+ */
cmd_handle_t cmd_exit;
+/**
+ * \brief \c test command
+ *
+ * ```
+ * (pbc) test
+ * ```
+ *
+ * Send a test command containing the ASCII string "Hello world!" to I2C
+ * address 0x39. This command takes no arguments.
+ */
cmd_handle_t cmd_test;
+/**
+ * \brief \c help command
+ *
+ * ```
+ * (pbc) help
+ * ```
+ *
+ * Print a list of available commands with descriptions. This command takes no
+ * arguments.
+ */
cmd_handle_t cmd_help;
+/**
+ * \brief \c reset command
+ *
+ * ```
+ * (pbc) reset <mod>
+ * ```
+ *
+ * Set a specific puzzle module's global state to *idle*. *mod* is the I2C
+ * address of the puzzle module to reset. This parameter may be specified in
+ * hexadecimal using a *0x* prefix or decimal.
+ *
+ */
cmd_handle_t cmd_reset;
+/**
+ * \brief \c send command
+ *
+ * ```
+ * (pbc) send <addr> <data>
+ * ```
+ *
+ * Send arbitrary data specified by *data* to the I2C address specified by
+ * *addr*. *data* may consist of multiple arguments separated by \ref IFS, in
+ * which case the arguments are concatenated.
+ *
+ * The main controller will initiate an I2C write command if the address
+ * specified in *addr* does not match that of the main controller. If the
+ * addresses do match, the main controller interprets the message as if it were
+ * being addressed by another I2C controller.
+ *
+ * \par Example
+ * ```
+ * ADDRESS DATA
+ * v~~~ v~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * (pbc) send 0x39 68:65:6c:6c:6f 44 0x20 'world' 33
+ * ^~~~~~~~~~~~~~ ^~ ^~~~ ^~~~~~~ ^~
+ * HEXSTR NUMBER NUMBER STRING NUMBER
+ * (binary) (dec) (hex) (literal) (dec)
+ * ```
+ *
+ * \par Datatypes
+ * \parblock
+ * - **NUMBER**
+ *
+ * Numbers can be specified as decimal or hexadecimal using a "0x" prefix.
+ * All numbers are unsigned. Decimal literals are always cast to 8-bit
+ * integers, while hexadecimal literals are cast to the smallest type that
+ * will fit the specified number. Numbers are always sent as little endian.
+ *
+ * Examples: `0` `123` `255` `0x10` `0x1245` `0xdeadBEEF`
+ *
+ * - **HEXSTR**
+ *
+ * Hexadecimal string literals are specified by hexadecimal bytes separated
+ * by colons. Each byte must be exactly 2 hexadecimal characters long and
+ * followed by a colon (except for the last byte). The minimum length of a
+ * hexstr is 2 bytes, as it must include at least a single colon.
+ *
+ * Examples: `de:ad:be:ef` `00:00`
+ *
+ * - **STRING**
+ *
+ * A string literal starts and ends with a single quote. All characters within
+ * this literal are sent as-is, and no escaping is possible.
+ *
+ * Examples: <code>'Hello world!'</code> <code>'string'</code> <code>' hello
+ * '</code>
+ *
+ * When double quotes are used instead of single quotes, the following escape
+ * sequences are recognised and replaced with special characters:
+ * |input|replacement|meaning|
+ * |-|-|-|
+ * |`\0`|0x00|null|
+ * |`\t`|0x09|tab|
+ * |`\n`|0x0a|newline|
+ * |`\r`|0x0d|carriage return|
+ * |`\\`|0x5c|backslash|
+ * |`\"`|0x22|double quote|
+ * |<code>\'</code>|0x27|single quote|
+ *
+ * Examples: `"Hello world!\\0"` `"foo\\nbar"`
+ * \endparblock
+ */
cmd_handle_t cmd_send;
+/**
+ * \brief \c skip command
+ *
+ * ```
+ * (pbc) skip <mod>
+ * ```
+ *
+ * Set a specific puzzle module's global state to *solved*. *mod* is the I2C
+ * address of the puzzle module to skip. This parameter may be specified in
+ * hexadecimal using a *0x* prefix or decimal.
+ *
+ */
cmd_handle_t cmd_skip;
+/**
+ * \brief \c dump command
+ */
cmd_handle_t cmd_dump;
+
+/// \}
+
+//! \c dump completion function
cmd_complete_t cmd_dump_complete;
//! Commands
diff --git a/client/pbc.1 b/client/pbc.1
deleted file mode 100644
index a85b03a..0000000
--- a/client/pbc.1
+++ /dev/null
@@ -1,90 +0,0 @@
-\# vim: ft=groff
-.de I2C
-I\*{2\*}C
-..
-.TH pbc 1
-.SH NAME
-pbc \- puzzle box client
-.SH SYNPOSIS
-pbc <addr> [port]
-.SH DESCRIPTION
-Connect to a puzzle box at the IPv4 address specified by \fIaddr\fP and
-optionally port specified by \fIport\fP. The default port is 9191. Once
-connected, a
-.MR readline 3 -based
-CLI is started, and commands can be sent.
-.SH COMMANDS
-.TP
-exit
-Disconnect from the puzzle box and exit pbc. This command takes no arguments.
-.TP
-help
-Print a list of available commands with descriptions. This command takes no
-arguments.
-.TP
-reset [mod ...]
-Set the main controller or specific puzzle module's global state to \fIidle\fP.
-If no modules are specified, the main controller's state is updated. One or
-more modules can be specified to update them at once.
-.TP
-skip [mod ...]
-Set the main controller or specific puzzle module's global state to
-\fIsolved\fP. If no modules are specified, the main controller's state is
-updated. One or more modules can be specified to update them at once.
-.SH DEBUG COMMANDS
-The commands detailed under this section are only available in version of pbc
-compiled with debug support.
-.TP
-send <addr> <data>
-Send arbitrary data specified by \fIdata\fP to the
-.I2C
-address specified by \fIaddr\fP. \fIdata\fP may consist of multiple arguments
-separated by IFS, in which case the arguments are concatenated.
-.TP
-test
-Send a test command containing the ASCII string "Hello world!" to
-.I2C
-address 0x39. This command takes no arguments.
-.SH DATA FORMATS
-.TP
-number
-Numbers can be specified as decimal or hexadecimal using a "0x" prefix. All
-numbers are unsigned. Decimal literals are always cast to 8-bit integers, while
-hexadecimal literals are cast to the smallest type that will fit the specified
-number. Numbers are always sent as little endian.
-
-Examples: 0 123 255 0x10 0x1245 0xdeadBEEF
-.TP
-hexstr
-Hexadecimal string literals are specified by hexadecimal bytes separated by
-colons. Each byte must be exactly 2 hexadecimal characters long and followed by
-a colon (except for the last byte). The minimum length of a hexstr is 2 bytes,
-as it must include at least a single colon.
-
-Examples: de:ad:be:ef 00:00
-.TP
-string
-A string literal starts and ends with a single quote. All characters within
-this literal are sent as-is, and no escaping is possible.
-
-Examples: 'Hello world!' 'string' ' hello '
-
-When double quotes are used instead of single quotes, the following escape
-sequences are recognised and replaced with special characters:
-
-\\0 -> 0x00 (null)
-.br
-\\t -> 0x09 (tab)
-.br
-\\n -> 0x0a (newline)
-.br
-\\r -> 0x0d (carriage return)
-.br
-\\\\ -> 0x5c (backslash)
-.br
-\\" -> 0x22 (double quote)
-.br
-\\' -> 0x27 (single quote)
-
-Examples: "Hello world!\\0" "foo\\nbar"
-
diff --git a/client/readme.md b/client/readme.md
index b9e0b09..d99991f 100644
--- a/client/readme.md
+++ b/client/readme.md
@@ -18,31 +18,12 @@ arbitrary data over the puzzle bus.
- Request puzzle box state
- Debug: send arbitrary messages
-## Building
-
-PBC is a standard CMake project.
-
-## Using
-
-See ./pbc.1 for usage.
-
-## Send data
-
-```
- ADDRESS DATA
- v~~~ v~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-send 0x39 68:65:6c:6c:6f 44 0x20 'world' 33
- ^~~~~~~~~~~~~~ ^~ ^~~~ ^~~~~~~ ^~
- HEXSTR NUMBER NUMBER STRING NUMBER
- (binary) (dec) (hex) (literal) (dec)
-```
-
-The data is concatenated, and may contain mixed types of literals
+## Usage
+See \ref pbc_cmd_usage "command usage" for individual command usage.
## 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 493f753..82d1412 100644
--- a/client/rl.cpp
+++ b/client/rl.cpp
@@ -128,18 +128,17 @@ int rl_word(const char * line, int cursor) {
return word;
}
-/// \internal
typedef struct {
const char * word;
const char ** options;
-} __rl_complete_list_data_t;
+} _rl_complete_list_data_t;
char** rl_complete_list(const char * word, const char ** options) {
- __rl_complete_list_data_t data = {
+ _rl_complete_list_data_t data = {
.word = word,
.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;
+ _rl_complete_list_data_t data = *(_rl_complete_list_data_t *) text;
static size_t i = 0;
if (state == 0) i = 0;
diff --git a/client/sock.h b/client/sock.h
index 792123e..5b62861 100644
--- a/client/sock.h
+++ b/client/sock.h
@@ -18,6 +18,7 @@
class PBSocket {
public:
PBSocket();
+ //! Constructor that immediately calls \c set_server()
PBSocket(const char * addr, uint16_t port);
virtual ~PBSocket();
diff --git a/lib/pbdrv/drv/arduino/mod.cpp b/lib/pbdrv/drv/arduino/mod.cpp
index 581b80a..81735af 100644
--- a/lib/pbdrv/drv/arduino/mod.cpp
+++ b/lib/pbdrv/drv/arduino/mod.cpp
@@ -47,11 +47,11 @@ static void pb_setup() {
* 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) {
- if (pb_hook_i2c_send(addr, buf, sz)) return;
+__weak void pb_i2c_send(i2c_addr_t i2c_addr, const uint8_t * buf, size_t sz) {
+ if (pb_hook_i2c_send(i2c_addr, buf, sz)) return;
vTaskDelay(10 / portTICK_PERIOD_MS); // prevent bus collisions
- Wire.beginTransmission((int) addr);
+ Wire.beginTransmission((int) i2c_addr);
Wire.write(buf, sz);
Wire.endTransmission(true);
Wire.setWireTimeout(PB_TIMEOUT_US, true);
diff --git a/lib/pbdrv/drv/index.dox b/lib/pbdrv/drv/index.dox
index 89b9247..c0c1b76 100644
--- a/lib/pbdrv/drv/index.dox
+++ b/lib/pbdrv/drv/index.dox
@@ -8,12 +8,17 @@ 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:
+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
+ \note The \c pb_i2c_send() function should immediately call \c
+ pb_hook_i2c_send() before doing any further processing:
+ ```c
+ if (pb_hook_i2c_send(i2c_addr, buf, sz)) return;
+ ```
*/
diff --git a/lib/pbdrv/index.dox b/lib/pbdrv/index.dox
index 8ddcb6a..0be5f33 100644
--- a/lib/pbdrv/index.dox
+++ b/lib/pbdrv/index.dox
@@ -68,6 +68,11 @@ extend or conditionally replace the default handlers), without needing to
completely overwrite the built-in handlers or understand the internals of \ref
pbdrv-mod.
+The boolean value returned by some hooks (e.g. those under \ref pb_hook_route
+or \ref pb_hook_i2c) represents if the default handler should run after the
+hook returns. This allow you to conditionally 'catch' calls to their respective
+base functions by returning \c true.
+
\}
*/
diff --git a/lib/pbdrv/mod/main/pb-mod-main.h b/lib/pbdrv/mod/main/pb-mod-main.h
deleted file mode 100644
index 9c69c1d..0000000
--- a/lib/pbdrv/mod/main/pb-mod-main.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include "../../pb-types.h"
-
-typedef struct {
- i2c_addr_t mod_addr;
- pb_global_state_t mod_state;
-} pb_mod_main_prop_mod_t;
-
-enum {
- PB_MOD_MAIN_PROP_MODS = 0x00, //!< structured list of connected puzzle modules
-};
-
diff --git a/lib/pbdrv/pb-mod.h b/lib/pbdrv/pb-mod.h
index 7069b32..21e8100 100644
--- a/lib/pbdrv/pb-mod.h
+++ b/lib/pbdrv/pb-mod.h
@@ -75,16 +75,16 @@ void pb_i2c_send(i2c_addr_t i2c_addr, const uint8_t * buf, size_t sz);
*/
/**
- * \brief global state read hook
- * \return current value of global state enum
+ * \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
+ * \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.
@@ -101,7 +101,23 @@ void pb_hook_mod_state_write(pb_global_state_t state);
* \{
*/
+/**
+ * \brief \c pb_i2c_recv() hook
+ *
+ * The default implementation of this function immediately returns \c false.
+ *
+ * \return \c false if execution should continue to the default handler, or \c
+ * true if it should stop (i.e. the message was handled).
+ */
bool pb_hook_i2c_recv(const uint8_t * buf, size_t sz);
+/**
+ * \brief \c pb_i2c_send() hook
+ *
+ * The default implementation of this function immediately returns \c false.
+ *
+ * \return \c false if execution should continue to the default handler, or \c
+ * true if it should stop (i.e. the message was handled).
+ */
bool pb_hook_i2c_send(i2c_addr_t i2c_addr, const uint8_t * buf, size_t sz);
/// \}
diff --git a/lib/pbdrv/pb-route.h b/lib/pbdrv/pb-route.h
index 2a28c0b..8b7bba5 100644
--- a/lib/pbdrv/pb-route.h
+++ b/lib/pbdrv/pb-route.h
@@ -140,10 +140,10 @@ void pb_route_cmd_magic_res(pb_msg_t * msg);
/**
* \brief \c pb_route_msg() hook
*
- * The default implementation of this function immediately returns false.
+ * The default implementation of this function immediately returns \c 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).
+ * \return \c false if execution should continue to the default handler, or \c
+ * true if it should stop (i.e. the message was handled).
*/
bool pb_hook_route_msg(pb_msg_t * msg);
diff --git a/main/config.def.h b/main/config.def.h
index cb6e8b4..1ec8a5c 100644
--- a/main/config.def.h
+++ b/main/config.def.h
@@ -71,10 +71,10 @@
#ifdef CFG_NET_DISABLE
#undef CFG_NET_COUNTRY
+//! Radio communications country
#define CFG_NET_COUNTRY CYW43_COUNTRY_WORLDWIDE
#endif
#ifndef CFG_NET_COUNTRY
-//! Radio communications country
#define CFG_NET_COUNTRY CYW43_COUNTRY_NETHERLANDS
#endif
/// \}
diff --git a/main/i2c.c b/main/i2c.c
index 19027b3..b68d0e0 100644
--- a/main/i2c.c
+++ b/main/i2c.c
@@ -12,6 +12,7 @@
#include "pb-buf.h"
#include "pb-send.h"
+//! Puzzle module handle
typedef struct {
i2c_addr_t sender; //!< I2C address of sender
pb_global_state_t state; //!< global state