diff options
-rw-r--r-- | client/CMakeLists.txt | 4 | ||||
-rw-r--r-- | client/cmd.cpp | 4 | ||||
-rw-r--r-- | client/examples/puzbus-hello-world.cpp | 67 | ||||
-rw-r--r-- | client/readme.md | 12 | ||||
-rw-r--r-- | client/sock.cpp | 12 | ||||
-rw-r--r-- | i2ctcp/i2ctcpv1.c (renamed from proto/puzbusv1.c) | 15 | ||||
-rw-r--r-- | i2ctcp/i2ctcpv1.h (renamed from proto/puzbusv1.h) | 42 | ||||
-rw-r--r-- | i2ctcp/include.cmake (renamed from proto/include.cmake) | 4 | ||||
l--------- | i2ctcp/lib (renamed from proto/lib) | 0 | ||||
-rw-r--r-- | main/CMakeLists.txt | 4 | ||||
-rw-r--r-- | main/sock.c | 12 | ||||
-rw-r--r-- | shared/busaddr.h | 20 | ||||
-rw-r--r-- | shared/puzbus.h | 39 |
13 files changed, 78 insertions, 157 deletions
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 6aa4b4f..73c703d 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_BUILD_TYPE Debug) project(puzzlebox_client C CXX) -include(../proto/include.cmake) +include(../i2ctcp/include.cmake) add_executable(pbc main.cpp @@ -19,7 +19,7 @@ add_executable(pbc ) target_link_libraries(pbc - puzbus + i2ctcp mpack readline # this is such a common library that I did not bother adding it as a submodule ) diff --git a/client/cmd.cpp b/client/cmd.cpp index 736cf12..a26de13 100644 --- a/client/cmd.cpp +++ b/client/cmd.cpp @@ -3,11 +3,11 @@ #include <string.h> #include "cmd.h" -#include "puzbusv1.h" +#include "i2ctcpv1.h" #include "sock.h" #include "parse.h" -#include "../shared/busaddr.h" +#include "../shared/puzbus.h" char* consume_token(char* input, const char* ifs) { strtok(input, ifs); diff --git a/client/examples/puzbus-hello-world.cpp b/client/examples/puzbus-hello-world.cpp deleted file mode 100644 index dcc965b..0000000 --- a/client/examples/puzbus-hello-world.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <unistd.h> - -#include "puzbusv1.h" - -int send_message() { - const char* data = "Test message data!"; - struct pb_msg output = { - .addr = 0x39, - .data = (char*) data, - .length = strlen(data), - }; - - char* packed; - size_t size; - if (!pb_write(&output, &packed, &size)) { - printf("error writing!\n"); - return EXIT_FAILURE; - } - - fwrite(packed, sizeof(packed[0]), size, stdout); - fflush(stdout); - - return EXIT_SUCCESS; -} - -int read_message() { - freopen(NULL, "rb", stdin); // allow binary on stdin - struct pb_msg input; - - char buf[4]; // extremely small buffer to test chunked message parsing - size_t bytes = 0; - - while ((bytes = fread(buf, sizeof(buf[0]), sizeof(buf), stdin)) > 0) { - int ret = pb_read(&input, buf, bytes); - - // header read error - if (ret < 0) { - printf("error reading!\n"); - return EXIT_FAILURE; - } - - // continue reading if more bytes needed... - if (ret > 0) continue; - - // message read completely! - printf("address: 0x%02x\n", input.addr); - printf("data: \"%.*s\"\n", input.length, input.data); - free(input.data); - return EXIT_SUCCESS; - } - - // if we reach this point, data was read but it did not contain a complete - // message, and is thus considered a failure - return EXIT_FAILURE; -} - -int main() { - if (!isatty(fileno(stdout))) return send_message(); - if (!isatty(fileno(stdin))) return read_message(); - - printf("please pipe some data in or out to use this program\n"); - return EXIT_SUCCESS; -} - diff --git a/client/readme.md b/client/readme.md index 98cd853..1b4cc34 100644 --- a/client/readme.md +++ b/client/readme.md @@ -1,17 +1,5 @@ # puzzle box client -goal (in order of implementation): -``` -(pbc) help - exit exit pbc - test send a test puzbus message - help show this help - send <addr> <data> [debug] send raw message - status show global puzzle box state (main controller state) - reset reset entire game state - ls list connected puzzle modules -``` - ## Send data ``` diff --git a/client/sock.cpp b/client/sock.cpp index f967f64..2d5787d 100644 --- a/client/sock.cpp +++ b/client/sock.cpp @@ -10,7 +10,7 @@ #include <thread> -#include "puzbusv1.h" +#include "i2ctcpv1.h" #include "sock.h" #include "rl.h" @@ -72,7 +72,7 @@ void PBSocket::send(const char * buf, size_t buf_sz) { } void PBSocket::sock_task() { - struct pb_msg input; + i2ctcp_msg_t input; while(1) { char buf[80]; @@ -86,11 +86,11 @@ void PBSocket::sock_task() { // skip empty frames if (bytes == 0) continue; - int ret = pb_read(&input, buf, bytes); + int ret = i2ctcp_read(&input, buf, bytes); // header read error if (ret < 0) { - rl_printf("pb_read error!\n"); + rl_printf("i2ctcp_read error!\n"); break; } @@ -106,7 +106,7 @@ void PBSocket::sock_task() { } void i2c_send(uint16_t addr, const char * data, size_t data_size) { - struct pb_msg msg = { + i2ctcp_msg_t msg = { .addr = addr, .data = (char *) data, .length = data_size, @@ -114,7 +114,7 @@ void i2c_send(uint16_t addr, const char * data, size_t data_size) { char* packed; size_t size; - if (!pb_write(&msg, &packed, &size)) return; + if (!i2ctcp_write(&msg, &packed, &size)) return; sock->send(packed, size); } diff --git a/proto/puzbusv1.c b/i2ctcp/i2ctcpv1.c index 73deda5..36a5dbd 100644 --- a/proto/puzbusv1.c +++ b/i2ctcp/i2ctcpv1.c @@ -3,11 +3,10 @@ // MIN() macro #include <sys/param.h> -// TODO: check if this works on pico as well -#include "puzbusv1.h" +#include "i2ctcpv1.h" -int pb_read(struct pb_msg * target, const char * buf, size_t buf_sz) { +int i2ctcp_read(i2ctcp_msg_t * target, const char * buf, size_t buf_sz) { // a new reader is used per buffer block passed to this function mpack_reader_t reader; mpack_reader_init_data(&reader, buf, buf_sz); @@ -17,9 +16,9 @@ int pb_read(struct pb_msg * target, const char * buf, size_t buf_sz) { // NOTE: The entire start of a message needs to be readable from the buffer // at this point. When target->addr can be read and target->length is past // the end of the current buffer block, this function will crash and burn. - // This is a highly unlikely scenario, as pb_read is called for each chunk - // of a TCP frame, and frames (should) include only one puzzle bus message. - // The check here is kind of optional. + // This is a highly unlikely scenario, as i2ctcp_read is called for each + // chunk of a TCP frame, and frames (should) include only one puzzle bus + // message. The check here is kind of optional. if (buf_sz < 4) return -1; target->addr = mpack_expect_u16(&reader); @@ -38,11 +37,11 @@ int pb_read(struct pb_msg * target, const char * buf, size_t buf_sz) { return target->_rdata; } -void pb_read_reset(struct pb_msg * target) { +void i2ctcp_read_reset(i2ctcp_msg_t * target) { target->_rdata = 0; } -bool pb_write(const struct pb_msg * target, char ** buf, size_t * buf_sz) { +bool i2ctcp_write(const i2ctcp_msg_t * target, char ** buf, size_t * buf_sz) { mpack_writer_t writer; mpack_writer_init_growable(&writer, buf, buf_sz); diff --git a/proto/puzbusv1.h b/i2ctcp/i2ctcpv1.h index 9f4f8e5..799b668 100644 --- a/proto/puzbusv1.h +++ b/i2ctcp/i2ctcpv1.h @@ -7,20 +7,21 @@ extern "C" { #endif -/** \brief Puzzle bus message (v1) */ -struct pb_msg { +/** \brief I2C over TCP message (v1) */ +struct i2ctcp_msg { uint16_t addr; //!< I^2^C 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; /** * \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 pb_write() + * assumed to only contain messages encoded by \p i2ctcp_write() * * \param target pointer to struct that will contain the finished message data * \param buf pointer to input stream data chunk @@ -34,24 +35,24 @@ struct pb_msg { * the message is not fully parsed. This variable must be `free()`d by the * caller after each complete message to prevent memory leaks. */ -int pb_read(struct pb_msg * target, const char * buf, size_t buf_sz); +int i2ctcp_read(i2ctcp_msg_t * target, const char * buf, size_t buf_sz); /** * \brief reset the remaining message data counter * - * Calling this function has the effect of forcing \c pb_read() to parse the - * next buffer chunk as the start of a new message. This function may be called - * before reading a TCP frame's data to mitigate any synchronization issues - * arising from earlier corrupt or otherwise malformed messages. + * 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 + * called before reading a TCP frame's data to mitigate any synchronization + * issues arising from earlier corrupt or otherwise malformed messages. */ -void pb_read_reset(struct pb_msg * target); +void i2ctcp_read_reset(i2ctcp_msg_t * target); /** * \brief Allocate and write a msgpack-formatted message to \p buf * * 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 pb_read() + * decoded later using \p i2ctcp_read() * * \param target pointer to struct that contains the message data * \param buf pointer to \c char* that will contain the formatted message @@ -62,26 +63,7 @@ void pb_read_reset(struct pb_msg * target); * * \note the pointer stored in \p buf must be `free()`d by the caller afterwards */ -bool pb_write(const struct pb_msg * target, char ** buf, size_t * buf_sz); - -/** - * \brief I^2^C puzzle bus command types - * - * The first byte of a puzzle bus message's data indicates the command type. - */ -enum pb_cmd { - PB_CMD_READ, //!< read a puzzle module property - PB_CMD_WRITE, //!< write to a puzzle module property - // PB_CMD_UPDATE, //!< request an update -}; - -/** \brief Puzzle bus global states */ -enum pb_global_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 -}; +bool i2ctcp_write(const i2ctcp_msg_t * target, char ** buf, size_t * buf_sz); #ifdef __cplusplus } diff --git a/proto/include.cmake b/i2ctcp/include.cmake index ac1305e..d755b57 100644 --- a/proto/include.cmake +++ b/i2ctcp/include.cmake @@ -1,6 +1,6 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}) -add_library(puzbus STATIC - ${CMAKE_CURRENT_LIST_DIR}/puzbusv1.c +add_library(i2ctcp STATIC + ${CMAKE_CURRENT_LIST_DIR}/i2ctcpv1.c ) # mpack diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 30685a4..6390d7c 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -7,7 +7,7 @@ set(PICO_BOARD pico_w) include(lib/pico-sdk/pico_sdk_init.cmake) include(lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/FreeRTOS_Kernel_import.cmake) -include(../proto/include.cmake) +include(../i2ctcp/include.cmake) project(puzzlebox_main C CXX ASM) @@ -33,7 +33,7 @@ target_link_libraries(main hardware_i2c FreeRTOS-Kernel FreeRTOS-Kernel-Heap4 - puzbus + i2ctcp mpack ) diff --git a/main/sock.c b/main/sock.c index 4f50981..fe932bb 100644 --- a/main/sock.c +++ b/main/sock.c @@ -7,16 +7,16 @@ #include "init.h" #include "config.h" -#include "puzbusv1.h" +#include "i2ctcpv1.h" #include "sock.h" struct netconn* current_connection = NULL; -struct pb_msg recv_msg; +i2ctcp_msg_t recv_msg; void i2c_send(uint16_t addr, const char * data, size_t data_size) { if (current_connection == NULL) return; - struct pb_msg send_msg = { + i2ctcp_msg_t send_msg = { .addr = addr, .data = (char *) data, .length = data_size, @@ -25,7 +25,7 @@ void i2c_send(uint16_t addr, const char * data, size_t data_size) { char * buf; size_t buf_sz; - if (!pb_write(&send_msg, &buf, &buf_sz)) return; + if (!i2ctcp_write(&send_msg, &buf, &buf_sz)) return; // NOTE: netconn does return an error code, but the data needs to be freed // whether netconn throws an error or not, so it remains unused @@ -47,7 +47,7 @@ void i2c_recv(uint16_t addr, const char * data, size_t data_size) { } void recv_handler(struct netconn* conn, struct netbuf* buf) { - pb_read_reset(&recv_msg); + i2ctcp_read_reset(&recv_msg); do { char* data; @@ -55,7 +55,7 @@ void recv_handler(struct netconn* conn, struct netbuf* buf) { netbuf_data(buf, (void**)&data, &len); // continue early if more data is needed to complete message - if (!pb_read(&recv_msg, data, len)) continue; + if (!i2ctcp_read(&recv_msg, data, len)) continue; // forward received message to puzzle bus i2c_recv(recv_msg.addr, recv_msg.data, recv_msg.length); diff --git a/shared/busaddr.h b/shared/busaddr.h deleted file mode 100644 index 5879afe..0000000 --- a/shared/busaddr.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -/** \file bus address reference */ - -// 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/puzbus.h b/shared/puzbus.h new file mode 100644 index 0000000..59a8867 --- /dev/null +++ b/shared/puzbus.h @@ -0,0 +1,39 @@ +#pragma once + +/** \file bus address reference */ + +// 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 + +/** + * \brief puzzle bus command types + * + * The first byte of a puzzle bus message's data indicates the command type. + */ +enum pb_cmd { + PB_CMD_READ, //!< read a puzzle module property + PB_CMD_WRITE, //!< write to a puzzle module property + // PB_CMD_UPDATE, //!< request an update +}; + +/** \brief Puzzle bus global states */ +enum pb_global_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 +}; + |