diff options
Diffstat (limited to 'shared')
-rw-r--r-- | shared/include.cmake | 5 | ||||
-rw-r--r-- | shared/pb/bus.h | 18 | ||||
-rw-r--r-- | shared/pb/mod/main.h | 13 | ||||
-rw-r--r-- | shared/pb/moddrv.c | 118 | ||||
-rw-r--r-- | shared/pb/moddrv.h | 62 | ||||
-rw-r--r-- | shared/pb/spec.adoc | 133 | ||||
-rw-r--r-- | shared/pb/types.h | 78 |
7 files changed, 0 insertions, 427 deletions
diff --git a/shared/include.cmake b/shared/include.cmake deleted file mode 100644 index c4b01c2..0000000 --- a/shared/include.cmake +++ /dev/null @@ -1,5 +0,0 @@ -include_directories(${CMAKE_CURRENT_LIST_DIR}) -add_library(puzbus STATIC - ${CMAKE_CURRENT_LIST_DIR}/pb/moddrv.c - ) - diff --git a/shared/pb/bus.h b/shared/pb/bus.h deleted file mode 100644 index 6f464c3..0000000 --- a/shared/pb/bus.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -// Adafruit NeoTrellis modules -#define BUSADDR_ADA_NEO_1 0x2E -#define BUSADDR_ADA_NEO_2 0x2F -#define BUSADDR_ADA_NEO_3 0x30 -#define BUSADDR_ADA_NEO_4 0x32 - -// TODO: ??? -#define BUSADDR_MOD_NEOTRELLIS 0 -#define BUSADDR_MOD_SOFTWARE 0 -#define BUSADDR_MOD_HARDWARE 0 -#define BUSADDR_MOD_VAULT 0 -// #define BUSADDR_MOD_AUTOMATION 0 - -// main controller -#define BUSADDR_MAIN 0x00 - diff --git a/shared/pb/mod/main.h b/shared/pb/mod/main.h deleted file mode 100644 index 56ccd3d..0000000 --- a/shared/pb/mod/main.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include "../types.h" - -typedef struct __packed { - const uint8_t addr; - const enum pb_state state; -} pb_mod_main_mod_t; - -enum __packed { - PB_MOD_MAIN_ADDR_MODS = 0x01, //!< connected puzzle modules -}; - diff --git a/shared/pb/moddrv.c b/shared/pb/moddrv.c deleted file mode 100644 index 1f7fab8..0000000 --- a/shared/pb/moddrv.c +++ /dev/null @@ -1,118 +0,0 @@ -#include <memory.h> - -#include "types.h" -#include "moddrv.h" - -/** \brief [private] placeholder global state variable */ -static enum pb_state _global_state = PB_GS_NOINIT; - -/** \brief [private] main controller global state */ -static enum pb_state _main_state = PB_GS_NOINIT; - -__weak enum pb_state pbdrv_hook_mod_state_read() { - return _global_state; -} - -__weak void pbdrv_hook_mod_state_write(enum pb_state state) { - _global_state = state; -} - -__weak void pbdrv_i2c_recv(uint16_t i2c_addr, const char * buf, size_t sz) { - if (sz == 0) return; - enum pb_cmd cmd = (enum pb_cmd) buf[0]; - - // shift buffer pointer to only contain the puzzle bus message buf - buf++; - sz--; - - // allow user to implement custom commands - if (pbdrv_hook_cmd(i2c_addr, cmd, buf, sz)) - return; - - switch (cmd) { - case PB_CMD_READ: return pbdrv_handle_read(i2c_addr, buf, sz); - case PB_CMD_WRITE: return pbdrv_handle_write(i2c_addr, buf, sz); - case PB_CMD_MAGIC: return pbdrv_handle_magic(i2c_addr, buf, sz); - case PB_CMD_SEX: return pbdrv_handle_sex(i2c_addr, buf, sz); - default: return; - } -} - -__weak void pbdrv_handle_read(uint16_t i2c_addr, const char * buf, size_t sz) { - if (sz == 0) return; - pb_cmd_read_t * cmd = (pb_cmd_read_t *) buf; - - // allow user to addrimplement custom read handlers - if (pbdrv_hook_read(i2c_addr, cmd->address)) - return; - - switch (cmd->address) { - case PB_ADDR_GS: { - char res[] = { - PB_CMD_READ, - PB_ADDR_GS, - pbdrv_hook_mod_state_read(), - }; - return pbdrv_i2c_send(i2c_addr, res, sizeof(res)); - } - default: return; - } -} - -__weak void pbdrv_handle_write(uint16_t i2c_addr, const char * buf, size_t sz) { - if (sz < 2) return; // must have address and at least 1 byte data - pb_cmd_write_t * cmd = (pb_cmd_write_t *) buf; - - // allow user to implement custom read handlers - if (pbdrv_hook_write(i2c_addr, cmd->address, (char *) cmd->data, sz - 1)) - return; - - switch (cmd->address) { - case PB_ADDR_GS: - pbdrv_hook_mod_state_write(cmd->data[0]); - break; - default: return; - } -} - -__weak void pbdrv_handle_magic(uint16_t i2c_addr, const char * buf, size_t sz) { - if (sz != sizeof(pb_magic_msg)) return; - if (memcmp(buf, pb_magic_msg, sizeof(pb_magic_msg)) != 0) return; - - size_t res_size = sizeof(pb_cmd_t) + sizeof(pb_magic_res); - char res[res_size]; - res[0] = PB_CMD_MAGIC; - memcpy(res, pb_magic_res, sizeof(pb_magic_res)); - - pbdrv_i2c_send(i2c_addr, res, res_size); -} - -__weak void pbdrv_handle_sex(uint16_t i2c_addr, const char * buf, size_t sz) { - if (sz == 0) return; - pb_cmd_sex_t * cmd = (pb_cmd_sex_t *) buf; - - // send own state - char res[] = { - PB_CMD_SEX, - pbdrv_hook_mod_state_read(), - }; - pbdrv_i2c_send(i2c_addr, res, sizeof(res)); - - if (cmd->main_state == _main_state) return; - // keep main controller state - _main_state = cmd->main_state; - // call update if main state changed - pbdrv_hook_main_state_update(_main_state); -} - -__weak void pbdrv_hook_main_state_update(enum pb_state state) { } -__weak bool pbdrv_hook_cmd(uint16_t i2c_addr, enum pb_state cmd, const char * buf, size_t sz) { - return false; -} -__weak bool pbdrv_hook_read(uint16_t i2c_addr, uint8_t addr) { - return false; -} -__weak bool pbdrv_hook_write(uint16_t i2c_addr, uint8_t addr, const char * buf, size_t sz) { - return false; -} - diff --git a/shared/pb/moddrv.h b/shared/pb/moddrv.h deleted file mode 100644 index ecfc13a..0000000 --- a/shared/pb/moddrv.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -/** - * \file puzzle bus driver implementation - * - * Most \c pbdrv_* 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 <stdint.h> -#include <stddef.h> -#include <stdbool.h> - -#include "types.h" - -#ifndef PBDRV_MOD_NAME -#define PBDRV_MOD_NAME "???" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -void pbdrv_i2c_recv(uint16_t i2c_addr, const char * buf, size_t sz); -void pbdrv_i2c_send(uint16_t i2c_addr, const char * buf, size_t sz); - -enum pb_state pbdrv_hook_mod_state_read(); -void pbdrv_hook_mod_state_write(enum pb_state state); -void pbdrv_hook_main_state_update(enum pb_state state); - -/** - * \name hooks - * - * Implementing this function allows you to use the weak implementation of \c - * pbdrv_i2c_recv() while being able to implement custom command handlers. - * - * \return true if the cmd was recognized, or false to forward the command to - * the default handlers - * - * \{ - */ - -/** \brief cmd receive hook */ -bool pbdrv_hook_cmd(uint16_t i2c_addr, enum pb_state cmd, const char * buf, size_t sz); -/** \brief read cmd hook */ -bool pbdrv_hook_read(uint16_t i2c_addr, uint8_t addr); -/** \brief write cmd hook */ -bool pbdrv_hook_write(uint16_t i2c_addr, uint8_t addr, const char * buf, size_t sz); -//! \} - -void pbdrv_handle_read(uint16_t i2c_addr, const char * buf, size_t sz); -void pbdrv_handle_write(uint16_t i2c_addr, const char * buf, size_t sz); -void pbdrv_handle_magic(uint16_t i2c_addr, const char * buf, size_t sz); -void pbdrv_handle_sex(uint16_t i2c_addr, const char * buf, size_t sz); - -#ifdef __cplusplus -} -#endif - diff --git a/shared/pb/spec.adoc b/shared/pb/spec.adoc deleted file mode 100644 index 3172e84..0000000 --- a/shared/pb/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/shared/pb/types.h b/shared/pb/types.h deleted file mode 100644 index d4a65ed..0000000 --- a/shared/pb/types.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __GNUC__ -#ifndef __packed -#define __packed __attribute__((packed)) -#endif -#ifndef __weak -#define __weak __attribute__((weak)) -#endif -#endif -#ifndef __packed -#error Could not determine packed attribute for current compiler -#define __packed -#endif -#ifndef __weak -#error Could not determine weak attribute for current compiler -#define __weak -#endif - -/** - * \brief puzzle bus command types - * - * The first byte of a puzzle bus message's data indicates the command type. - */ -enum __packed pb_cmd { - PB_CMD_READ, //!< read a puzzle module property - PB_CMD_WRITE, //!< write to a puzzle module property - PB_CMD_SEX, //!< state exchange - PB_CMD_MAGIC, //!< magic message -}; -// typedef enum pb_cmd pb_cmd_t; - -/** \brief magic sent from main controller to puzzle module */ -static const char pb_magic_msg[] = { 0x70, 0x75, 0x7a, 0x62, 0x75, 0x73 }; -/** \brief magic reply from puzzle module back to main controller */ -static const char pb_magic_res[] = { 0x67, 0x61, 0x6d, 0x69, 0x6e, 0x67 }; - -/** \brief Puzzle bus global states */ -enum __packed pb_state { - 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_state pb_state_t; - -typedef struct __packed { - const enum pb_cmd cmd; - const uint8_t data[]; -} pb_cmd_t; - -typedef struct __packed { - const uint8_t address; - const uint8_t data[]; -} pb_cmd_read_t; - -typedef struct __packed { - const uint8_t address; - const uint8_t data[]; -} pb_cmd_write_t; - -typedef struct __packed { - const enum pb_state main_state; -} pb_cmd_sex_t; - -enum __packed { - PB_ADDR_GS = 0x00, //!< global state address -}; - -#ifdef __cplusplus -} -#endif - |