diff options
Diffstat (limited to 'puzzle/spec.adoc')
-rw-r--r-- | puzzle/spec.adoc | 158 |
1 files changed, 0 insertions, 158 deletions
diff --git a/puzzle/spec.adoc b/puzzle/spec.adoc deleted file mode 100644 index fbd1033..0000000 --- a/puzzle/spec.adoc +++ /dev/null @@ -1,158 +0,0 @@ -= Puzzle module specification - -This document contains a subset of the puzzle bus protocol specification, and -is targeted at puzzle module developers. It describes the required -implementation steps for integrating a new game into the puzzle module -framework. All constants and types mentioned in this document are defined in a -C header: link:../shared/puzbus.h[]. - -== 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]. This -document only describes the *data* that is sent over the I^2^C bus. Addresses -also influence the puzzle box's behavior, and are also further explained in the -Design document. - -== Messages - -All puzzle bus messages follow the following format: - -[%autowidth] -|=== -| ``pb_cmd_t command`` | ``uint8_t data[]`` -|=== - -The format of ``data[]`` is determined by the message type. These messages are -the core of the puzzle bus framework, and follow these rules: - -- Only the main controller takes initiative to send messages (i.e. puzzle - modules wait until they are asked to give information, and do not immediately - send new information when internal updates occur, etc.) -- Puzzle modules can only reply to messages sent from the main controller -- Messages from the main controller to puzzle modules are sent as *I^2^C read* - commands (even ``PB_CMD_WRITE`` commands) -- Reponses from the puzzle modules back to the main contorller are sent as - *I^2^C write* commands - -In order to properly integrate with the puzzle module framework, a puzzle -module must do the following: - -- <<sec:cmd-magic,Respond to the 'magic message'>> -- Keep a global state variable of type ``pb_state_t`` -- <<sec:state-global,Implement the exchange command>> -- <<sec:state-aux,Implement address 0 for the read and write commands>> - -[[sec:cmd-magic]] -=== Magic - -The puzzle module will receive a message of type ``PB_CMD_MAGIC`` with data -being equal to ``pb_magic_msg``. Upon verifying that the message data indeed -matches ``pb_magic_msg``, the puzzle module sends back a message of type -``PB_CMD_MAGIC`` with data ``pb_magic_res``. This concludes the puzzle module -registration process. - -Example C code: - -```c -#include "puzbus.h" - -void pb_cmd_magic_handler(const char * data, size_t sz) { - if (strncmp(buf, pb_magic_msg, sizeof(pb_magic_msg)) != 0) return; - - const char res[] = { - PB_CMD_MAGIC, - pb_magic_res, - }; - - i2c_write(BUSADDR_MAIN, res, sizeof(res)); -} - -void i2c_read_handle(uint16_t addr, const char * buf, size_t sz) { - if (sz < 1) return; - pb_cmd_t cmd = (pb_cmd_t) buf[0]; - - // shift buffer pointer to only contain the puzzle bus message data - buf++; sz--; - - if (cmd == PB_CMD_MAGIC) pb_cmd_magic_handler(buf, sz); -} -``` - -[[sec:state-global]] -=== Global state - -Each puzzle module keeps a single 'global state' variable of type -``pb_state_t`` that represents the abstracted state of the implemented game. -Games may implement additional state variables, but the global state is -required for integration with the puzzle framework. - -IMPORTANT: Keep in mind that the global state may be overwritten by a game -operator, which the puzzle module must be able to handle and react to -accordingly. Writing to state variables is explained further in the section -about <<sec:state-aux,auxiliary state variables>>. - -The main controller periodically informs each puzzle module of the combined -puzzle box state, and simultaniously requests each module's state back. This -message has type ``PB_CMD_EXCHANGE``, and the ``data[]`` of this message -includes a single ``pb_state_t`` representing the combined box state. The -puzzle module responds to this message with a message of type -``PB_CMD_EXCHANGE``, where ``data[]`` is the puzzle module's own global state. - -Example C code: - -```c -#include "puzbus.h" -pb_state_t module_state = PB_STATE_NOINIT; - -void pb_cmd_exchange_handler(const char * data, size_t sz) { - if (sz < 1) return; - pb_state_t main_state = (pb_state_t) data[0]; - - // printf("main state is now %d\n", main_state); - - const char res[] = { - PB_CMD_EXCHANGE, - (char) module_state, - }; - - i2c_write(BUSADDR_MAIN, res, sizeof(res)); -} - -// if (cmd == PB_CMD_EXCHANGE) pb_cmd_exchange_handler(buf, sz); -// (see above listing) -``` - -[[sec:state-aux]] -=== Auxiliary state - -The ``PB_CMD_READ`` command may be used to read game state variables exposed to -the puzzle bus interface directly. This command has the following format: - -[%autowidth] -|=== -| ``PB_CMD_READ`` | ``uint8_t address`` -|=== - -Similarly, a ``PB_CMD_WRITE`` command exists for writing to these variables: - -[%autowidth] -|=== -| ``PB_CMD_WRITE`` | ``uint8_t address`` | ``char data[]`` -|=== - -The format of ``data[]`` is determined by the data type at ``address``. Puzzle -modules are required to have a <<sec:state-global,global state>> variable, and -the global state *must* be readable and writeable on address 0. This results in -``address[0]`` always having a data type of ``pb_state_t``. All other addresses -are unused by the puzzle module framework, and may be used for implementing -puzzle-specific functionality. - -When a puzzle module receives a ``PB_CMD_READ`` command, it will reply with -``PB_CMD_WRITE`` to the main controller with the same address, but with -``data[]`` now filled with the corresponding data at ``address``. - -NOTE: The ``PB_CMD_WRITE`` reply must be an *I^2^C write* command to avoid -being interpreted as a write requests from the puzzle module to the main -controller. - |