From a8b794c02574e96150d55852fa5db1ce7529503d Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 5 Jun 2024 12:51:24 +0200 Subject: add arduino cmake toolchain + improve lazy.mk --- lib/Arduino-CMake-Toolchain | 1 + 1 file changed, 1 insertion(+) create mode 160000 lib/Arduino-CMake-Toolchain (limited to 'lib') diff --git a/lib/Arduino-CMake-Toolchain b/lib/Arduino-CMake-Toolchain new file mode 160000 index 0000000..e745a9b --- /dev/null +++ b/lib/Arduino-CMake-Toolchain @@ -0,0 +1 @@ +Subproject commit e745a9bed3c3fb83442d55bf05630f31574674f2 -- cgit v1.2.3 From d9093e3245f9619850cea391adcad1a12164d38e Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 5 Jun 2024 16:32:46 +0200 Subject: the large library cleanup --- .gitmodules | 4 +- client/CMakeLists.txt | 8 ++- client/compile_commands.json | 1 - client/i2c.cpp | 4 +- i2ctcp/i2ctcpv1.c | 52 ----------------- i2ctcp/i2ctcpv1.h | 71 ---------------------- i2ctcp/include.cmake | 19 ------ i2ctcp/lib | 1 - i2ctcp/readme.md | 25 -------- lib/i2ctcp/CMakeLists.txt | 14 +++++ lib/i2ctcp/i2ctcpv1.c | 52 +++++++++++++++++ lib/i2ctcp/i2ctcpv1.h | 71 ++++++++++++++++++++++ lib/i2ctcp/makefile | 4 ++ lib/i2ctcp/readme.md | 25 ++++++++ lib/mpack | 1 - lib/mpack/CMakeLists.txt | 26 +++++++++ lib/mpack/makefile | 4 ++ lib/mpack/src | 1 + lib/pbdrv/CMakeLists.txt | 40 +++++++++++++ lib/pbdrv/drv/arduino/mod.cpp | 33 +++++++++++ lib/pbdrv/drv/arduino/mod.h | 19 ++++++ lib/pbdrv/makefile | 4 ++ lib/pbdrv/mod/main.h | 13 +++++ lib/pbdrv/pb-mod.c | 26 +++++++++ lib/pbdrv/pb-mod.h | 34 +++++++++++ lib/pbdrv/pb-read.c | 3 + lib/pbdrv/pb-read.h | 2 + lib/pbdrv/pb-types.h | 91 +++++++++++++++++++++++++++++ lib/pbdrv/pb-write.c | 1 + lib/pbdrv/pb-write.h | 3 + lib/pbdrv/pb.h | 18 ++++++ lib/pbdrv/spec.adoc | 133 ++++++++++++++++++++++++++++++++++++++++++ main/CMakeLists.txt | 3 +- main/compile_commands.json | 1 - puzzle/dummy/CMakeLists.txt | 2 +- puzzle/dummy/main.cpp | 7 +-- shared/pb.cmake | 20 ------- shared/pb/bus.h | 18 ------ shared/pb/drv/arduino/mod.cpp | 33 ----------- shared/pb/drv/arduino/mod.h | 19 ------ shared/pb/mod/main.h | 13 ----- shared/pb/moddrv.c | 25 -------- shared/pb/moddrv.h | 32 ---------- shared/pb/spec.adoc | 133 ------------------------------------------ shared/pb/types.h | 90 ---------------------------- test/CMakeLists.txt | 7 +-- 46 files changed, 634 insertions(+), 572 deletions(-) delete mode 120000 client/compile_commands.json delete mode 100644 i2ctcp/i2ctcpv1.c delete mode 100644 i2ctcp/i2ctcpv1.h delete mode 100644 i2ctcp/include.cmake delete mode 120000 i2ctcp/lib delete mode 100644 i2ctcp/readme.md create mode 100644 lib/i2ctcp/CMakeLists.txt create mode 100644 lib/i2ctcp/i2ctcpv1.c create mode 100644 lib/i2ctcp/i2ctcpv1.h create mode 100644 lib/i2ctcp/makefile create mode 100644 lib/i2ctcp/readme.md delete mode 160000 lib/mpack create mode 100644 lib/mpack/CMakeLists.txt create mode 100644 lib/mpack/makefile create mode 160000 lib/mpack/src create mode 100644 lib/pbdrv/CMakeLists.txt create mode 100644 lib/pbdrv/drv/arduino/mod.cpp create mode 100644 lib/pbdrv/drv/arduino/mod.h create mode 100644 lib/pbdrv/makefile create mode 100644 lib/pbdrv/mod/main.h create mode 100644 lib/pbdrv/pb-mod.c create mode 100644 lib/pbdrv/pb-mod.h create mode 100644 lib/pbdrv/pb-read.c create mode 100644 lib/pbdrv/pb-read.h create mode 100644 lib/pbdrv/pb-types.h create mode 100644 lib/pbdrv/pb-write.c create mode 100644 lib/pbdrv/pb-write.h create mode 100644 lib/pbdrv/pb.h create mode 100644 lib/pbdrv/spec.adoc delete mode 120000 main/compile_commands.json delete mode 100644 shared/pb.cmake delete mode 100644 shared/pb/bus.h delete mode 100644 shared/pb/drv/arduino/mod.cpp delete mode 100644 shared/pb/drv/arduino/mod.h delete mode 100644 shared/pb/mod/main.h delete mode 100644 shared/pb/moddrv.c delete mode 100644 shared/pb/moddrv.h delete mode 100644 shared/pb/spec.adoc delete mode 100644 shared/pb/types.h (limited to 'lib') diff --git a/.gitmodules b/.gitmodules index 6313925..9ff7e96 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,8 +13,8 @@ url = https://github.com/FreeRTOS/FreeRTOS-Kernel branch = V11.1.0 shallow = true -[submodule "lib/mpack"] - path = lib/mpack +[submodule "lib/mpack/src"] + path = lib/mpack/src url = https://github.com/ludocode/mpack branch = v1.1.1 shallow = true diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index b1cfbaf..7d492b0 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -8,10 +8,11 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS 1) set(CMAKE_BUILD_TYPE Debug) add_compile_definitions(DEBUG) -project(puzzlebox_client C CXX) +project(pbc C CXX) -include(../i2ctcp/include.cmake) -include(../shared/pb.cmake) +add_subdirectory(lib/mpack) +add_subdirectory(lib/i2ctcp) +add_subdirectory(lib/pbdrv) add_executable(pbc main.cpp @@ -27,5 +28,6 @@ target_link_libraries(pbc i2ctcp mpack readline # this is such a common library that I did not bother adding it as a submodule + pbdrv ) diff --git a/client/compile_commands.json b/client/compile_commands.json deleted file mode 120000 index 25eb4b2..0000000 --- a/client/compile_commands.json +++ /dev/null @@ -1 +0,0 @@ -build/compile_commands.json \ No newline at end of file diff --git a/client/i2c.cpp b/client/i2c.cpp index 951f654..4dbc724 100644 --- a/client/i2c.cpp +++ b/client/i2c.cpp @@ -5,8 +5,8 @@ #include "sock.h" #include "xxd.h" -#include "pb/bus.h" -#include "pb/types.h" +#include "pb.h" +#include "pb-types.h" // #include "pb/mod/main.h" diff --git a/i2ctcp/i2ctcpv1.c b/i2ctcp/i2ctcpv1.c deleted file mode 100644 index 944df3a..0000000 --- a/i2ctcp/i2ctcpv1.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#include "i2ctcpv1.h" - -int i2ctcp_read(i2ctcp_msg_t * target, const char * buf, size_t buf_sz) { - mpack_reader_t reader; - mpack_reader_init_data(&reader, buf, buf_sz); - - // at start of message - if (target->_rdata == 0) { - target->addr = mpack_expect_u16(&reader); - target->length = target->_rdata = mpack_expect_bin(&reader); - if (mpack_reader_error(&reader) != mpack_ok) return -1; - target->data = (char *) malloc(target->length); - - // seek forward in buf to where binary data begins (to avoid having to read - // from private member reader.data in the memcpy below) - buf += buf_sz - mpack_reader_remaining(&reader, NULL); - } - - // continue reading chunks of target->data until the amount of bytes - // specified in target->length - size_t to_read = MIN(mpack_reader_remaining(&reader, NULL), target->_rdata); - char * data = target->data + target->length - target->_rdata; - memcpy(data, buf, to_read); - target->_rdata -= to_read; - // NOTE: memcpy is used here because mpack_read_bytes requires that a tag was - // opened, which is not the case for the chunks following the initial mpack - // header - - // if rdata = 0, the message was completely read - return target->_rdata; -} - -void i2ctcp_read_reset(i2ctcp_msg_t * target) { - target->_rdata = 0; -} - -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); - - mpack_write_u16(&writer, target->addr); - mpack_write_bin(&writer, target->data, target->length); - - // finish writing - return mpack_writer_destroy(&writer) == mpack_ok; -} - diff --git a/i2ctcp/i2ctcpv1.h b/i2ctcp/i2ctcpv1.h deleted file mode 100644 index 799b668..0000000 --- a/i2ctcp/i2ctcpv1.h +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** \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 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 - * - * \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 - * 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 - * - * 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 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 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 - * - * \returns boolean true if a the message could be encoded successfully, false - * if there was some kind of error - * - * \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/i2ctcp/include.cmake b/i2ctcp/include.cmake deleted file mode 100644 index b61b2a4..0000000 --- a/i2ctcp/include.cmake +++ /dev/null @@ -1,19 +0,0 @@ -include_directories(${CMAKE_CURRENT_LIST_DIR}) -add_library(i2ctcp STATIC - ${CMAKE_CURRENT_LIST_DIR}/i2ctcpv1.c - ) - -# mpack -include_directories(${CMAKE_CURRENT_LIST_DIR}/lib/mpack/src/mpack) -add_library(mpack STATIC - ${CMAKE_CURRENT_LIST_DIR}/lib/mpack/src/mpack/mpack-common.c - ${CMAKE_CURRENT_LIST_DIR}/lib/mpack/src/mpack/mpack-expect.c - ${CMAKE_CURRENT_LIST_DIR}/lib/mpack/src/mpack/mpack-node.c - ${CMAKE_CURRENT_LIST_DIR}/lib/mpack/src/mpack/mpack-platform.c - ${CMAKE_CURRENT_LIST_DIR}/lib/mpack/src/mpack/mpack-reader.c - ${CMAKE_CURRENT_LIST_DIR}/lib/mpack/src/mpack/mpack-writer.c - ) - -# causes some wild crashes, please leave off -add_compile_definitions(MPACK_READ_TRACKING=0) - diff --git a/i2ctcp/lib b/i2ctcp/lib deleted file mode 120000 index dc598c5..0000000 --- a/i2ctcp/lib +++ /dev/null @@ -1 +0,0 @@ -../lib \ No newline at end of file diff --git a/i2ctcp/readme.md b/i2ctcp/readme.md deleted file mode 100644 index d5bfe6d..0000000 --- a/i2ctcp/readme.md +++ /dev/null @@ -1,25 +0,0 @@ -# i2ctcp (I2C over TCP) - -This folder includes protocol (de)serialization functions for sending and -receiving I2C 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/i2ctcp/CMakeLists.txt b/lib/i2ctcp/CMakeLists.txt new file mode 100644 index 0000000..b47b1d7 --- /dev/null +++ b/lib/i2ctcp/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.29) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) + +project(i2ctcp C CXX) + +add_subdirectory(../mpack ${CMAKE_CURRENT_BINARY_DIR}/mpack) + +add_library(i2ctcp STATIC ./i2ctcpv1.c) +target_link_libraries(i2ctcp mpack) +target_include_directories(i2ctcp SYSTEM INTERFACE .) + diff --git a/lib/i2ctcp/i2ctcpv1.c b/lib/i2ctcp/i2ctcpv1.c new file mode 100644 index 0000000..944df3a --- /dev/null +++ b/lib/i2ctcp/i2ctcpv1.c @@ -0,0 +1,52 @@ +#include +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#include "i2ctcpv1.h" + +int i2ctcp_read(i2ctcp_msg_t * target, const char * buf, size_t buf_sz) { + mpack_reader_t reader; + mpack_reader_init_data(&reader, buf, buf_sz); + + // at start of message + if (target->_rdata == 0) { + target->addr = mpack_expect_u16(&reader); + target->length = target->_rdata = mpack_expect_bin(&reader); + if (mpack_reader_error(&reader) != mpack_ok) return -1; + target->data = (char *) malloc(target->length); + + // seek forward in buf to where binary data begins (to avoid having to read + // from private member reader.data in the memcpy below) + buf += buf_sz - mpack_reader_remaining(&reader, NULL); + } + + // continue reading chunks of target->data until the amount of bytes + // specified in target->length + size_t to_read = MIN(mpack_reader_remaining(&reader, NULL), target->_rdata); + char * data = target->data + target->length - target->_rdata; + memcpy(data, buf, to_read); + target->_rdata -= to_read; + // NOTE: memcpy is used here because mpack_read_bytes requires that a tag was + // opened, which is not the case for the chunks following the initial mpack + // header + + // if rdata = 0, the message was completely read + return target->_rdata; +} + +void i2ctcp_read_reset(i2ctcp_msg_t * target) { + target->_rdata = 0; +} + +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); + + mpack_write_u16(&writer, target->addr); + mpack_write_bin(&writer, target->data, target->length); + + // finish writing + return mpack_writer_destroy(&writer) == mpack_ok; +} + diff --git a/lib/i2ctcp/i2ctcpv1.h b/lib/i2ctcp/i2ctcpv1.h new file mode 100644 index 0000000..799b668 --- /dev/null +++ b/lib/i2ctcp/i2ctcpv1.h @@ -0,0 +1,71 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \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 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 + * + * \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 + * 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 + * + * 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 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 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 + * + * \returns boolean true if a the message could be encoded successfully, false + * if there was some kind of error + * + * \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/makefile b/lib/i2ctcp/makefile new file mode 100644 index 0000000..5ca3fd1 --- /dev/null +++ b/lib/i2ctcp/makefile @@ -0,0 +1,4 @@ +TARGET = $(BUILD_DIR)/libi2ctcp.a + +include ../../lazy.mk + diff --git a/lib/i2ctcp/readme.md b/lib/i2ctcp/readme.md new file mode 100644 index 0000000..d5bfe6d --- /dev/null +++ b/lib/i2ctcp/readme.md @@ -0,0 +1,25 @@ +# i2ctcp (I2C over TCP) + +This folder includes protocol (de)serialization functions for sending and +receiving I2C 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 b/lib/mpack deleted file mode 160000 index 79d3fcd..0000000 --- a/lib/mpack +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 79d3fcd3e04338b06e82d01a62f4aa98c7bad5f7 diff --git a/lib/mpack/CMakeLists.txt b/lib/mpack/CMakeLists.txt new file mode 100644 index 0000000..0a904b0 --- /dev/null +++ b/lib/mpack/CMakeLists.txt @@ -0,0 +1,26 @@ +if(TARGET mpack) + return() +endif() + +cmake_minimum_required(VERSION 3.29) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) + +project(mpack C) + +add_library(mpack STATIC + src/src/mpack/mpack-common.c + src/src/mpack/mpack-expect.c + src/src/mpack/mpack-node.c + src/src/mpack/mpack-platform.c + src/src/mpack/mpack-reader.c + src/src/mpack/mpack-writer.c + ) +target_include_directories(mpack SYSTEM INTERFACE + src/src/mpack + ) + +# causes some wild crashes, please leave off +add_compile_definitions(MPACK_READ_TRACKING=0) + diff --git a/lib/mpack/makefile b/lib/mpack/makefile new file mode 100644 index 0000000..e96794a --- /dev/null +++ b/lib/mpack/makefile @@ -0,0 +1,4 @@ +TARGET = $(BUILD_DIR)/libmpack.a + +include ../../lazy.mk + diff --git a/lib/mpack/src b/lib/mpack/src new file mode 160000 index 0000000..79d3fcd --- /dev/null +++ b/lib/mpack/src @@ -0,0 +1 @@ +Subproject commit 79d3fcd3e04338b06e82d01a62f4aa98c7bad5f7 diff --git a/lib/pbdrv/CMakeLists.txt b/lib/pbdrv/CMakeLists.txt new file mode 100644 index 0000000..08894cc --- /dev/null +++ b/lib/pbdrv/CMakeLists.txt @@ -0,0 +1,40 @@ +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) + +project(pbdrv C CXX) + +if(DEFINED ARDUINO) + set(PBDRV_ARDUINO true) +endif() + +include_directories(.) +add_library(pbdrv STATIC + pb-read.c + pb-write.c + ) +target_include_directories(pbdrv SYSTEM INTERFACE .) + +list(APPEND PBDRV_SRCS pb-mod.c) + +if(PBDRV_ARDUINO) + list(APPEND PBDRV_SRCS drv/arduino/mod.cpp) +endif() + +add_library(pbdrv-mod STATIC ${PBDRV_SRCS}) +target_link_libraries(pbdrv-mod pbdrv) +# add_dependencies(pbdrv-mod pbdrv) + +if(PBDRV_ARDUINO) + target_link_arduino_libraries(pbdrv-mod + core + Wire + ) +endif() + diff --git a/lib/pbdrv/drv/arduino/mod.cpp b/lib/pbdrv/drv/arduino/mod.cpp new file mode 100644 index 0000000..c7bbe45 --- /dev/null +++ b/lib/pbdrv/drv/arduino/mod.cpp @@ -0,0 +1,33 @@ +#ifndef ARDUINO +#error This driver only works on the Arduino platform! +#endif + +#include +#include + +#include +#include + +#include "mod.h" + +static void recv_event(int bytes) { + uint8_t * data = (uint8_t *) malloc(bytes); + size_t size = 0; + while (Wire.available()) { + data[size++] = Wire.read(); + } + + pbdrv_i2c_recv(data, size); +} + +void pbdrv_setup() { + Wire.begin((int) PBDRV_MOD_ADDR); + Wire.onReceive(recv_event); +} + +__weak void pbdrv_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) { + Wire.beginTransmission((int) addr); + Wire.write(buf, sz); + Wire.endTransmission(); +} + diff --git a/lib/pbdrv/drv/arduino/mod.h b/lib/pbdrv/drv/arduino/mod.h new file mode 100644 index 0000000..e545d9b --- /dev/null +++ b/lib/pbdrv/drv/arduino/mod.h @@ -0,0 +1,19 @@ +#pragma once + +#include "../../pb-mod.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief puzzle bus driver setup + * + * This function should be called from the Arduino \c setup() function. + */ +void pbdrv_setup(); + +#ifdef __cplusplus +} +#endif + diff --git a/lib/pbdrv/makefile b/lib/pbdrv/makefile new file mode 100644 index 0000000..c87d1af --- /dev/null +++ b/lib/pbdrv/makefile @@ -0,0 +1,4 @@ +TARGET = $(BUILD_DIR)/libpbdrv.a + +include ../../lazy.mk + diff --git a/lib/pbdrv/mod/main.h b/lib/pbdrv/mod/main.h new file mode 100644 index 0000000..535ce06 --- /dev/null +++ b/lib/pbdrv/mod/main.h @@ -0,0 +1,13 @@ +#pragma once + +#include "../types.h" + +typedef struct { + const i2c_addr_t mod_addr; + const pb_global_state_t mod_state; +} pb_mod_main_mod_t; + +enum { + PB_MOD_MAIN_ADDR_MODS = 0x01, //!< connected puzzle modules +}; + diff --git a/lib/pbdrv/pb-mod.c b/lib/pbdrv/pb-mod.c new file mode 100644 index 0000000..740f2a5 --- /dev/null +++ b/lib/pbdrv/pb-mod.c @@ -0,0 +1,26 @@ +#include "pb-types.h" +#include "pb.h" + +//! fallback module name +__weak const char * PBDRV_MOD_NAME = "???"; + +//! [private] placeholder global state variable +static pb_global_state_t _global_state = PB_GS_NOINIT; + +//! [private] main controller global state +static pb_global_state_t _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(const uint8_t * buf, size_t sz) { + return; +} + +__weak void pbdrv_hook_main_state_update(pb_global_state_t state) { } + diff --git a/lib/pbdrv/pb-mod.h b/lib/pbdrv/pb-mod.h new file mode 100644 index 0000000..fa290bf --- /dev/null +++ b/lib/pbdrv/pb-mod.h @@ -0,0 +1,34 @@ +#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 +#include +#include + +#include "pb-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//! puzzle module name (optional, default = "???") +extern const char * PBDRV_MOD_NAME; +//! puzzle module bus address (required) +extern const i2c_addr_t PBDRV_MOD_ADDR; + +void pbdrv_i2c_recv(const uint8_t * buf, size_t sz); +void pbdrv_i2c_send(i2c_addr_t i2c_addr, const uint8_t * buf, size_t sz); + +#ifdef __cplusplus +} +#endif + diff --git a/lib/pbdrv/pb-read.c b/lib/pbdrv/pb-read.c new file mode 100644 index 0000000..843420d --- /dev/null +++ b/lib/pbdrv/pb-read.c @@ -0,0 +1,3 @@ +#include "pb-read.h" + + diff --git a/lib/pbdrv/pb-read.h b/lib/pbdrv/pb-read.h new file mode 100644 index 0000000..3f59c93 --- /dev/null +++ b/lib/pbdrv/pb-read.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/lib/pbdrv/pb-types.h b/lib/pbdrv/pb-types.h new file mode 100644 index 0000000..3c1314f --- /dev/null +++ b/lib/pbdrv/pb-types.h @@ -0,0 +1,91 @@ +#pragma once +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __GNUC__ +#define __weak __attribute__((weak)) +#endif +#ifndef __weak +#error Could not determine weak attribute for current compiler +#define __weak +#endif + +typedef uint16_t i2c_addr_t; + +//! puzzle bus command types +enum pb_cmd_id { + PB_CMD_REQ_READ, //!< request a puzzle module property + PB_CMD_RES_READ, //!< respond to a puzzle module property request + PB_CMD_REQ_WRITE, //!< request to write a puzzle module property + PB_CMD_REQ_STATE, //!< request global state + PB_CMD_RES_STATE, //!< respond to a global state request + PB_CMD_MAGIC, //!< magic message (regular i2c command) +}; +typedef enum pb_cmd_id pb_cmd_id_t; + +//! magic sent from main controller to puzzle module +static const char pb_cmd_magic_msg[] = { 0x70, 0x75, 0x7a, 0x62, 0x75, 0x73 }; +//! magic reply from puzzle module back to main controller +static const char pb_cmd_magic_res[] = { 0x67, 0x61, 0x6d, 0x69, 0x6e, 0x67 }; + +//! 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 +}; +typedef enum pb_global_state pb_global_state_t; + +//! puzzle bus message header (shared by all commands) +typedef struct { + const pb_cmd_id_t type; //!< command type + const i2c_addr_t sender; //!< i2c address of sender +} pb_msg_header_t; + +//! PB_CMD_REQ_READ data +typedef struct { + const pb_msg_header_t header; + const uint8_t propid; //!< state property id to return +} pb_cmd_req_read_t; + +//! PB_CMD_RES_READ data +typedef struct { + const pb_msg_header_t header; + const uint8_t propid; //!< id of returned state property + const uint8_t value[]; +} pb_cmd_res_read_t; + +//! PB_CMD_REQ_WRITE data +typedef struct { + const pb_msg_header_t header; + const uint8_t propid; //!< state property id to write + const uint8_t value[]; //!< new value of property +} pb_cmd_req_write_t; + +//! PB_CMD_REQ_STATE data +typedef struct { + const pb_msg_header_t header; + const pb_global_state_t state; //!< global state of sender +} pb_cmd_req_state_t; + +//! PB_CMD_RES_STATE data +typedef struct { + const pb_msg_header_t header; + const pb_global_state_t state; //!< global state of sender +} pb_cmd_res_state_t; + +//! PB_CMD_MAGIC data +typedef struct { + const pb_msg_header_t header; + const char magic[]; //!< magic value +} pb_cmd_magic_t; + +#ifdef __cplusplus +} +#endif + diff --git a/lib/pbdrv/pb-write.c b/lib/pbdrv/pb-write.c new file mode 100644 index 0000000..65a2932 --- /dev/null +++ b/lib/pbdrv/pb-write.c @@ -0,0 +1 @@ +#include "pb-write.h" diff --git a/lib/pbdrv/pb-write.h b/lib/pbdrv/pb-write.h new file mode 100644 index 0000000..45dcbb0 --- /dev/null +++ b/lib/pbdrv/pb-write.h @@ -0,0 +1,3 @@ +#pragma once + + diff --git a/lib/pbdrv/pb.h b/lib/pbdrv/pb.h new file mode 100644 index 0000000..e37d785 --- /dev/null +++ b/lib/pbdrv/pb.h @@ -0,0 +1,18 @@ +#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_MOD_MAIN 0x00 + diff --git a/lib/pbdrv/spec.adoc b/lib/pbdrv/spec.adoc new file mode 100644 index 0000000..3172e84 --- /dev/null +++ b/lib/pbdrv/spec.adoc @@ -0,0 +1,133 @@ += 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 + <> 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 <>. +- If you want to implement custom puzzle bus commands, you can implement the + <>. + +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 6390d7c..70cd901 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -7,7 +7,8 @@ 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(../i2ctcp/include.cmake) +add_subdirectory(lib/mpack) +add_subdirectory(lib/i2ctcp) project(puzzlebox_main C CXX ASM) diff --git a/main/compile_commands.json b/main/compile_commands.json deleted file mode 120000 index 25eb4b2..0000000 --- a/main/compile_commands.json +++ /dev/null @@ -1 +0,0 @@ -build/compile_commands.json \ No newline at end of file diff --git a/puzzle/dummy/CMakeLists.txt b/puzzle/dummy/CMakeLists.txt index acc567c..435a2ad 100644 --- a/puzzle/dummy/CMakeLists.txt +++ b/puzzle/dummy/CMakeLists.txt @@ -14,7 +14,7 @@ set(ARDUINO_BOARD "Arduino Uno [avr.uno]") project(pb_mod_dummy C CXX) -include(../../shared/pb.cmake) +add_subdirectory(lib/pbdrv) add_executable(main main.cpp diff --git a/puzzle/dummy/main.cpp b/puzzle/dummy/main.cpp index edcc587..1c79441 100644 --- a/puzzle/dummy/main.cpp +++ b/puzzle/dummy/main.cpp @@ -1,7 +1,7 @@ #include #include -#include "pb/drv/arduino/mod.h" +#include "drv/arduino/mod.h" const char * PBDRV_MOD_NAME = "dummy"; const i2c_addr_t PBDRV_MOD_ADDR = 0x20; @@ -10,8 +10,5 @@ void setup() { pbdrv_setup(); } -void loop() { - pbdrv_i2c_send(0x00, (uint8_t *) "hoi", 3); - delay(100); -} +void loop() { } diff --git a/shared/pb.cmake b/shared/pb.cmake deleted file mode 100644 index 71a28cb..0000000 --- a/shared/pb.cmake +++ /dev/null @@ -1,20 +0,0 @@ -if(DEFINED ARDUINO) - set(PBDRV_ARDUINO true) -endif() - -include_directories(${CMAKE_CURRENT_LIST_DIR}) - -list(APPEND PBDRV_SRCS "${CMAKE_CURRENT_LIST_DIR}/pb/moddrv.c") - -if(PBDRV_ARDUINO) - list(APPEND PBDRV_SRCS "${CMAKE_CURRENT_LIST_DIR}/pb/drv/arduino/mod.cpp") -endif() - -add_library(pbdrv-mod STATIC ${PBDRV_SRCS}) - -if(PBDRV_ARDUINO) - target_link_arduino_libraries(pbdrv-mod - core - Wire - ) -endif() 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/drv/arduino/mod.cpp b/shared/pb/drv/arduino/mod.cpp deleted file mode 100644 index c7bbe45..0000000 --- a/shared/pb/drv/arduino/mod.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef ARDUINO -#error This driver only works on the Arduino platform! -#endif - -#include -#include - -#include -#include - -#include "mod.h" - -static void recv_event(int bytes) { - uint8_t * data = (uint8_t *) malloc(bytes); - size_t size = 0; - while (Wire.available()) { - data[size++] = Wire.read(); - } - - pbdrv_i2c_recv(data, size); -} - -void pbdrv_setup() { - Wire.begin((int) PBDRV_MOD_ADDR); - Wire.onReceive(recv_event); -} - -__weak void pbdrv_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) { - Wire.beginTransmission((int) addr); - Wire.write(buf, sz); - Wire.endTransmission(); -} - diff --git a/shared/pb/drv/arduino/mod.h b/shared/pb/drv/arduino/mod.h deleted file mode 100644 index e2e3b6d..0000000 --- a/shared/pb/drv/arduino/mod.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "../../moddrv.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief puzzle bus driver setup - * - * This function should be called from the Arduino \c setup() function. - */ -void pbdrv_setup(); - -#ifdef __cplusplus -} -#endif - 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 b17b7ac..0000000 --- a/shared/pb/moddrv.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "types.h" -#include "moddrv.h" - -//! fallback module name -__weak const char * PBDRV_MOD_NAME = "???"; - -//! [private] placeholder global state variable -static pb_global_state_t _global_state = PB_GS_NOINIT; - -//! [private] main controller global state -static pb_global_state_t _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(const uint8_t * buf, size_t sz) { - return; -} - -__weak void pbdrv_hook_main_state_update(pb_global_state_t state) { } diff --git a/shared/pb/moddrv.h b/shared/pb/moddrv.h deleted file mode 100644 index b48f4db..0000000 --- a/shared/pb/moddrv.h +++ /dev/null @@ -1,32 +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 -#include -#include - -#include "types.h" - -extern const char * PBDRV_MOD_NAME; -extern const i2c_addr_t PBDRV_MOD_ADDR; - -#ifdef __cplusplus -extern "C" { -#endif - -void pbdrv_i2c_recv(const uint8_t * buf, size_t sz); -void pbdrv_i2c_send(i2c_addr_t i2c_addr, const uint8_t * 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 - <> 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 <>. -- If you want to implement custom puzzle bus commands, you can implement the - <>. - -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 186066b..0000000 --- a/shared/pb/types.h +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __GNUC__ -#define __weak __attribute__((weak)) -#endif -#ifndef __weak -#error Could not determine weak attribute for current compiler -#define __weak -#endif - -typedef uint16_t i2c_addr_t; - -//! puzzle bus command types -enum pb_cmd_id { - PB_CMD_REQ_READ, //!< request a puzzle module property - PB_CMD_RES_READ, //!< respond to a puzzle module property request - PB_CMD_REQ_WRITE, //!< request to write a puzzle module property - PB_CMD_REQ_STATE, //!< request global state - PB_CMD_RES_STATE, //!< respond to a global state request - PB_CMD_MAGIC, //!< magic message (regular i2c command) -}; -typedef enum pb_cmd_id pb_cmd_id_t; - -//! magic sent from main controller to puzzle module -static const char pb_cmd_magic_msg[] = { 0x70, 0x75, 0x7a, 0x62, 0x75, 0x73 }; -//! magic reply from puzzle module back to main controller -static const char pb_cmd_magic_res[] = { 0x67, 0x61, 0x6d, 0x69, 0x6e, 0x67 }; - -//! 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 -}; -typedef enum pb_global_state pb_global_state_t; - -//! puzzle bus message header (shared by all commands) -typedef struct { - const pb_cmd_id_t type; //!< command type - const i2c_addr_t sender; //!< i2c address of sender -} pb_msg_header_t; - -//! PB_CMD_REQ_READ data -typedef struct { - const pb_msg_header_t header; - const uint8_t propid; //!< state property id to return -} pb_cmd_req_read_t; - -//! PB_CMD_RES_READ data -typedef struct { - const pb_msg_header_t header; - const uint8_t propid; //!< id of returned state property - const uint8_t value[]; -} pb_cmd_res_read_t; - -//! PB_CMD_REQ_WRITE data -typedef struct { - const pb_msg_header_t header; - const uint8_t propid; //!< state property id to write - const uint8_t value[]; //!< new value of property -} pb_cmd_req_write_t; - -//! PB_CMD_REQ_STATE data -typedef struct { - const pb_msg_header_t header; - const pb_global_state_t state; //!< global state of sender -} pb_cmd_req_state_t; - -//! PB_CMD_RES_STATE data -typedef struct { - const pb_msg_header_t header; - const pb_global_state_t state; //!< global state of sender -} pb_cmd_res_state_t; - -//! PB_CMD_MAGIC data -typedef struct { - const pb_msg_header_t header; - const char magic[]; //!< magic value -} pb_cmd_magic_t; - -#ifdef __cplusplus -} -#endif - diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e139c34..818c533 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,21 +6,20 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS 1) project(pbtest C CXX ASM) -include(../i2ctcp/include.cmake) -include(../shared/pb.cmake) - add_executable(test ExampleTest.cpp i2ctcp/main.cpp ) -# enable_testing() add_subdirectory(lib/googletest) +add_subdirectory(lib/pbdrv) +add_subdirectory(lib/i2ctcp) # target_include_directories(tests PRIVATE ${CMAKE_CURRENT_LIST_DIR}) target_link_libraries(test gtest_main i2ctcp mpack + pbdrv ) -- cgit v1.2.3 From 68471e5800b81285453a26547721d264dbcf49b9 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 5 Jun 2024 16:48:59 +0200 Subject: add `mpack_read_remaining_bytes` function to mpack --- lib/i2ctcp/i2ctcpv1.c | 11 +---------- lib/mpack/CMakeLists.txt | 2 ++ lib/mpack/mpack.h | 19 +++++++++++++++++++ lib/mpack/read-remaining.c | 10 ++++++++++ 4 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 lib/mpack/mpack.h create mode 100644 lib/mpack/read-remaining.c (limited to 'lib') diff --git a/lib/i2ctcp/i2ctcpv1.c b/lib/i2ctcp/i2ctcpv1.c index 944df3a..f70cbb1 100644 --- a/lib/i2ctcp/i2ctcpv1.c +++ b/lib/i2ctcp/i2ctcpv1.c @@ -15,21 +15,12 @@ int i2ctcp_read(i2ctcp_msg_t * target, const char * buf, size_t buf_sz) { target->length = target->_rdata = mpack_expect_bin(&reader); if (mpack_reader_error(&reader) != mpack_ok) return -1; target->data = (char *) malloc(target->length); - - // seek forward in buf to where binary data begins (to avoid having to read - // from private member reader.data in the memcpy below) - buf += buf_sz - mpack_reader_remaining(&reader, NULL); } // continue reading chunks of target->data until the amount of bytes // specified in target->length - size_t to_read = MIN(mpack_reader_remaining(&reader, NULL), target->_rdata); char * data = target->data + target->length - target->_rdata; - memcpy(data, buf, to_read); - target->_rdata -= to_read; - // NOTE: memcpy is used here because mpack_read_bytes requires that a tag was - // opened, which is not the case for the chunks following the initial mpack - // header + target->_rdata -= mpack_read_remaining_bytes(&reader, data, target->_rdata); // if rdata = 0, the message was completely read return target->_rdata; diff --git a/lib/mpack/CMakeLists.txt b/lib/mpack/CMakeLists.txt index 0a904b0..0e4359d 100644 --- a/lib/mpack/CMakeLists.txt +++ b/lib/mpack/CMakeLists.txt @@ -16,8 +16,10 @@ add_library(mpack STATIC src/src/mpack/mpack-platform.c src/src/mpack/mpack-reader.c src/src/mpack/mpack-writer.c + read-remaining.c ) target_include_directories(mpack SYSTEM INTERFACE + . src/src/mpack ) diff --git a/lib/mpack/mpack.h b/lib/mpack/mpack.h new file mode 100644 index 0000000..7c0c089 --- /dev/null +++ b/lib/mpack/mpack.h @@ -0,0 +1,19 @@ +#pragma once + +#include "src/src/mpack/mpack.h" + +/** + * \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 + * + * 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 + */ +size_t mpack_read_remaining_bytes(mpack_reader_t * reader, char * p, size_t count); + diff --git a/lib/mpack/read-remaining.c b/lib/mpack/read-remaining.c new file mode 100644 index 0000000..ebc9b56 --- /dev/null +++ b/lib/mpack/read-remaining.c @@ -0,0 +1,10 @@ +#include "mpack.h" + +size_t mpack_read_remaining_bytes(mpack_reader_t * reader, char * p, size_t count) { + size_t limit =mpack_reader_remaining(reader, NULL); + if (0 < count && count < limit) + limit = count; + memcpy(p, reader->data, limit); + return limit; +} + -- cgit v1.2.3 From 0fc049aeaf3dab41e92ed0bd7872094d7c5c9bdc Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Wed, 5 Jun 2024 17:44:57 +0200 Subject: WIP pb-write cmd req set state --- lib/pbdrv/CMakeLists.txt | 5 +++++ lib/pbdrv/pb-read.h | 8 ++++++++ lib/pbdrv/pb-types.h | 7 +++++++ lib/pbdrv/pb-write.c | 34 ++++++++++++++++++++++++++++++++++ lib/pbdrv/pb-write.h | 23 +++++++++++++++++++++++ test/CMakeLists.txt | 3 +-- test/ExampleTest.cpp | 10 ---------- test/pbdrv/main.cpp | 18 ++++++++++++++++++ 8 files changed, 96 insertions(+), 12 deletions(-) delete mode 100644 test/ExampleTest.cpp create mode 100644 test/pbdrv/main.cpp (limited to 'lib') diff --git a/lib/pbdrv/CMakeLists.txt b/lib/pbdrv/CMakeLists.txt index 08894cc..dfaac01 100644 --- a/lib/pbdrv/CMakeLists.txt +++ b/lib/pbdrv/CMakeLists.txt @@ -10,6 +10,8 @@ add_compile_definitions(DEBUG) project(pbdrv C CXX) +add_subdirectory(../mpack ${CMAKE_CURRENT_BINARY_DIR}/mpack) + if(DEFINED ARDUINO) set(PBDRV_ARDUINO true) endif() @@ -19,6 +21,9 @@ add_library(pbdrv STATIC pb-read.c pb-write.c ) +target_link_libraries(pbdrv + mpack + ) target_include_directories(pbdrv SYSTEM INTERFACE .) list(APPEND PBDRV_SRCS pb-mod.c) diff --git a/lib/pbdrv/pb-read.h b/lib/pbdrv/pb-read.h index 3f59c93..7a6f0df 100644 --- a/lib/pbdrv/pb-read.h +++ b/lib/pbdrv/pb-read.h @@ -1,2 +1,10 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/lib/pbdrv/pb-types.h b/lib/pbdrv/pb-types.h index 3c1314f..96ffc37 100644 --- a/lib/pbdrv/pb-types.h +++ b/lib/pbdrv/pb-types.h @@ -23,6 +23,7 @@ enum pb_cmd_id { PB_CMD_REQ_WRITE, //!< request to write a puzzle module property PB_CMD_REQ_STATE, //!< request global state PB_CMD_RES_STATE, //!< respond to a global state request + PB_CMD_REQ_SET_STATE, //!< request to overwrite module global state PB_CMD_MAGIC, //!< magic message (regular i2c command) }; typedef enum pb_cmd_id pb_cmd_id_t; @@ -79,6 +80,12 @@ typedef struct { const pb_global_state_t state; //!< global state of sender } pb_cmd_res_state_t; +//! PB_CMD_REQ_SET_STATE data +typedef struct { + const pb_msg_header_t header; + const pb_global_state_t state; //!< new global state +} pb_cmd_req_set_state_t; + //! PB_CMD_MAGIC data typedef struct { const pb_msg_header_t header; diff --git a/lib/pbdrv/pb-write.c b/lib/pbdrv/pb-write.c index 65a2932..752a4ac 100644 --- a/lib/pbdrv/pb-write.c +++ b/lib/pbdrv/pb-write.c @@ -1 +1,35 @@ +#include + #include "pb-write.h" + +typedef struct { + mpack_writer_t writer; + pbdrv_buf_t buf; +} pbdrv_writer_t; + +static pbdrv_writer_t pbdrv_write_init() { + pbdrv_writer_t writer; + mpack_writer_init_growable(&writer.writer, &writer.buf.data, &writer.buf.size); + return writer; +} + +static pbdrv_buf_t pbdrv_write_finish(pbdrv_writer_t * writer) { + if (mpack_writer_destroy(&writer->writer) != mpack_ok) { + writer->buf.data = NULL; + writer->buf.size = 0; + } + return writer->buf; +} + +static void pbdrv_write_msg_header(pbdrv_writer_t * writer, pb_msg_header_t header) { + mpack_write_u8(&writer->writer, header.type); + mpack_write_u16(&writer->writer, header.sender); +} + +pbdrv_buf_t pbdrv_write_cmd_req_set_state(pb_cmd_req_set_state_t data) { + pbdrv_writer_t writer = pbdrv_write_init(); + pbdrv_write_msg_header(&writer, data.header); + mpack_write_u8(&writer.writer, data.state); + return pbdrv_write_finish(&writer); +} + diff --git a/lib/pbdrv/pb-write.h b/lib/pbdrv/pb-write.h index 45dcbb0..3245898 100644 --- a/lib/pbdrv/pb-write.h +++ b/lib/pbdrv/pb-write.h @@ -1,3 +1,26 @@ #pragma once +#include "pb-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +//! binary buffer struct +typedef struct { + char * data; //! pointer to data + size_t size; //! size of data +} pbdrv_buf_t; + +pbdrv_buf_t pbdrv_write_cmd_req_read(pb_cmd_req_read_t data); +pbdrv_buf_t pbdrv_write_cmd_res_read(pb_cmd_res_read_t data); +pbdrv_buf_t pbdrv_write_cmd_req_write(pb_cmd_req_write_t data); +pbdrv_buf_t pbdrv_write_cmd_req_state(pb_cmd_req_state_t data); +pbdrv_buf_t pbdrv_write_cmd_res_state(pb_cmd_res_state_t data); +pbdrv_buf_t pbdrv_write_cmd_req_set_state(pb_cmd_req_set_state_t data); +pbdrv_buf_t pbdrv_write_cmd_magic(pb_cmd_magic_t data); + +#ifdef __cplusplus +} +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 818c533..d5d6e0d 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,15 +7,14 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS 1) project(pbtest C CXX ASM) add_executable(test - ExampleTest.cpp i2ctcp/main.cpp + pbdrv/main.cpp ) add_subdirectory(lib/googletest) add_subdirectory(lib/pbdrv) add_subdirectory(lib/i2ctcp) -# target_include_directories(tests PRIVATE ${CMAKE_CURRENT_LIST_DIR}) target_link_libraries(test gtest_main i2ctcp diff --git a/test/ExampleTest.cpp b/test/ExampleTest.cpp deleted file mode 100644 index 3da58ff..0000000 --- a/test/ExampleTest.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include - -class ExampleTest : public testing::Test { -protected: -}; - -TEST_F(ExampleTest, Test) { - EXPECT_EQ(5, 5); -} - diff --git a/test/pbdrv/main.cpp b/test/pbdrv/main.cpp new file mode 100644 index 0000000..de7e88a --- /dev/null +++ b/test/pbdrv/main.cpp @@ -0,0 +1,18 @@ +#include + +#include "pb-write.h" + +TEST(pbdrv, write) { + + pbdrv_buf_t buf = pbdrv_write_cmd_req_set_state({ + .header = { .sender = 0xf0, }, + .state = PB_GS_PLAYING, + }); + for (size_t i = 0; i < buf.size; i++) { + printf("%02x ", buf.data[i] & 0xff); + } + printf("\n"); + + ASSERT_TRUE(true); +} + -- cgit v1.2.3 From c7aa2916dce4cd3d82ac1be42c433d1ed66db69e Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Thu, 6 Jun 2024 11:56:55 +0200 Subject: WIP debugging arduino puzzle module driver --- lib/pbdrv/drv/arduino/mod.cpp | 20 +++++++++++++++++--- lib/pbdrv/pb.h | 22 +++++++++++++--------- puzzle/dummy/main.cpp | 28 ++++++++++++++++++++++++++-- 3 files changed, 56 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/pbdrv/drv/arduino/mod.cpp b/lib/pbdrv/drv/arduino/mod.cpp index c7bbe45..2113ba2 100644 --- a/lib/pbdrv/drv/arduino/mod.cpp +++ b/lib/pbdrv/drv/arduino/mod.cpp @@ -8,6 +8,7 @@ #include #include +#include "../../pb.h" #include "mod.h" static void recv_event(int bytes) { @@ -22,12 +23,25 @@ static void recv_event(int bytes) { void pbdrv_setup() { Wire.begin((int) PBDRV_MOD_ADDR); + Wire.setWireTimeout(PB_TIMEOUT_US, true); + Wire.setClock(PB_CLOCK_SPEED_HZ); Wire.onReceive(recv_event); } __weak void pbdrv_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) { - Wire.beginTransmission((int) addr); - Wire.write(buf, sz); - Wire.endTransmission(); + uint8_t error; + uint8_t retry = 4; + do { + error = 0; + Wire.beginTransmission((int) addr); + size_t written = Wire.write(buf, sz); + if (written != sz) + error++; + error += Wire.endTransmission(true); + Wire.setWireTimeout(PB_TIMEOUT_US, true); + + if(retry == 0) break; + retry--; + } while (error); } diff --git a/lib/pbdrv/pb.h b/lib/pbdrv/pb.h index e37d785..b6efed0 100644 --- a/lib/pbdrv/pb.h +++ b/lib/pbdrv/pb.h @@ -1,18 +1,22 @@ #pragma once +#define PB_CLOCK_SPEED_HZ 100000 +#define PB_TIMEOUT_MS 10 +#define PB_TIMEOUT_US (1e3 * PB_TIMEOUT_MS) + // 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 +#define PB_ADDR_ADA_NEO_1 0x2E +#define PB_ADDR_ADA_NEO_2 0x2F +#define PB_ADDR_ADA_NEO_3 0x30 +#define PB_ADDR_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 PB_ADDR_MOD_NEOTRELLIS 0 +#define PB_ADDR_MOD_SOFTWARE 0 +#define PB_ADDR_MOD_HARDWARE 0 +#define PB_ADDR_MOD_VAULT 0 // #define BUSADDR_MOD_AUTOMATION 0 // main controller -#define BUSADDR_MOD_MAIN 0x00 +#define PB_ADDR_MOD_MAIN 0x00 diff --git a/puzzle/dummy/main.cpp b/puzzle/dummy/main.cpp index 1c79441..688549f 100644 --- a/puzzle/dummy/main.cpp +++ b/puzzle/dummy/main.cpp @@ -3,12 +3,36 @@ #include "drv/arduino/mod.h" +// #define THOMAS + +#ifdef THOMAS +#define ADDR_RX 0x69 +#define ADDR_TX 0x20 +#define MSG "hoi" +#define MSG_DELAY 10 +#else +#define ADDR_TX 0x69 +#define ADDR_RX 0x20 +#define MSG "dag" +#define MSG_DELAY 9 +#endif + const char * PBDRV_MOD_NAME = "dummy"; -const i2c_addr_t PBDRV_MOD_ADDR = 0x20; +const i2c_addr_t PBDRV_MOD_ADDR = ADDR_RX; void setup() { pbdrv_setup(); + Serial.begin(115200); + pinMode(4, OUTPUT); + digitalWrite(4, LOW); } -void loop() { } +void loop() { + pbdrv_i2c_send(ADDR_TX, (uint8_t *) MSG, 4); + delay(MSG_DELAY); +} + +void pbdrv_i2c_recv(const uint8_t * data, size_t size) { + Serial.println((char *) data); +} -- cgit v1.2.3 From 3f1e5a5c6a594601e597a43a125883d5e3c618c1 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 7 Jun 2024 16:56:19 +0200 Subject: added pull-up resistors (code works, commit for safety) --- lib/pbdrv/drv/arduino/mod.cpp | 3 +++ puzzle/dummy/main.cpp | 24 +++++++++++------------- puzzle/dummy/makefile | 14 +++++++++++++- 3 files changed, 27 insertions(+), 14 deletions(-) (limited to 'lib') diff --git a/lib/pbdrv/drv/arduino/mod.cpp b/lib/pbdrv/drv/arduino/mod.cpp index 2113ba2..a522ff8 100644 --- a/lib/pbdrv/drv/arduino/mod.cpp +++ b/lib/pbdrv/drv/arduino/mod.cpp @@ -43,5 +43,8 @@ __weak void pbdrv_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) { if(retry == 0) break; retry--; } while (error); + + if (error) + Serial.print(error, DEC); } diff --git a/puzzle/dummy/main.cpp b/puzzle/dummy/main.cpp index 688549f..4abe47a 100644 --- a/puzzle/dummy/main.cpp +++ b/puzzle/dummy/main.cpp @@ -3,18 +3,20 @@ #include "drv/arduino/mod.h" -// #define THOMAS - -#ifdef THOMAS +#ifdef TEST_A #define ADDR_RX 0x69 #define ADDR_TX 0x20 -#define MSG "hoi" +#define MSG "aa" +#define MSG_SIZE 3 #define MSG_DELAY 10 -#else +#endif + +#ifdef TEST_B #define ADDR_TX 0x69 #define ADDR_RX 0x20 -#define MSG "dag" -#define MSG_DELAY 9 +#define MSG "bbbbbbbb" +#define MSG_SIZE 9 +#define MSG_DELAY 10 #endif const char * PBDRV_MOD_NAME = "dummy"; @@ -23,16 +25,12 @@ const i2c_addr_t PBDRV_MOD_ADDR = ADDR_RX; void setup() { pbdrv_setup(); Serial.begin(115200); - pinMode(4, OUTPUT); - digitalWrite(4, LOW); } void loop() { - pbdrv_i2c_send(ADDR_TX, (uint8_t *) MSG, 4); + pbdrv_i2c_send(ADDR_TX, (uint8_t *) MSG, MSG_SIZE); delay(MSG_DELAY); } -void pbdrv_i2c_recv(const uint8_t * data, size_t size) { - Serial.println((char *) data); -} +void pbdrv_i2c_recv(const uint8_t * data, size_t size) { } diff --git a/puzzle/dummy/makefile b/puzzle/dummy/makefile index a971dfb..041054e 100644 --- a/puzzle/dummy/makefile +++ b/puzzle/dummy/makefile @@ -2,6 +2,18 @@ TARGET = $(BUILD_DIR)/main.elf include ../../lazy.mk -export SERIAL_PORT = /dev/ttyACM0 +export SERIAL_PORT ?= /dev/ttyACM0 flash: upload-main; +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 + -- cgit v1.2.3 From 1f01917a4d339f7c68b452afbf2275c4cbda6c80 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Fri, 7 Jun 2024 17:01:48 +0200 Subject: remove overengineered code --- lib/pbdrv/drv/arduino/mod.cpp | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) (limited to 'lib') diff --git a/lib/pbdrv/drv/arduino/mod.cpp b/lib/pbdrv/drv/arduino/mod.cpp index a522ff8..518a8a4 100644 --- a/lib/pbdrv/drv/arduino/mod.cpp +++ b/lib/pbdrv/drv/arduino/mod.cpp @@ -14,9 +14,8 @@ static void recv_event(int bytes) { uint8_t * data = (uint8_t *) malloc(bytes); size_t size = 0; - while (Wire.available()) { + while (Wire.available()) data[size++] = Wire.read(); - } pbdrv_i2c_recv(data, size); } @@ -29,22 +28,8 @@ void pbdrv_setup() { } __weak void pbdrv_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) { - uint8_t error; - uint8_t retry = 4; - do { - error = 0; - Wire.beginTransmission((int) addr); - size_t written = Wire.write(buf, sz); - if (written != sz) - error++; - error += Wire.endTransmission(true); - Wire.setWireTimeout(PB_TIMEOUT_US, true); - - if(retry == 0) break; - retry--; - } while (error); - - if (error) - Serial.print(error, DEC); + Wire.beginTransmission((int) addr); + Wire.write(buf, sz); + Wire.endTransmission(true); } -- cgit v1.2.3 From feaa43f37c01cf832fed17572d915e5709231893 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 8 Jun 2024 19:20:49 +0200 Subject: WIP raspberry pi pico pbdrv --- lib/pbdrv/CMakeLists.txt | 37 +++++------------ lib/pbdrv/drv/arduino/cfg.cmake | 7 ++++ lib/pbdrv/drv/arduino/mod.h | 2 - lib/pbdrv/drv/rp2040/cfg.cmake | 7 ++++ lib/pbdrv/drv/rp2040/mod.c | 50 +++++++++++++++++++++++ lib/pbdrv/drv/rp2040/mod.h | 13 ++++++ main/CMakeLists.txt | 3 +- main/config.def.h | 26 +++++++----- main/i2c.c | 90 ++++++++++++++++------------------------- main/i2c.h | 34 +--------------- main/init.c | 10 ++++- main/main.c | 6 +-- main/mod.c | 5 +++ 13 files changed, 157 insertions(+), 133 deletions(-) create mode 100644 lib/pbdrv/drv/arduino/cfg.cmake create mode 100644 lib/pbdrv/drv/rp2040/cfg.cmake create mode 100644 lib/pbdrv/drv/rp2040/mod.c create mode 100644 lib/pbdrv/drv/rp2040/mod.h create mode 100644 main/mod.c (limited to 'lib') diff --git a/lib/pbdrv/CMakeLists.txt b/lib/pbdrv/CMakeLists.txt index dfaac01..e70cb5b 100644 --- a/lib/pbdrv/CMakeLists.txt +++ b/lib/pbdrv/CMakeLists.txt @@ -12,34 +12,17 @@ project(pbdrv C CXX) add_subdirectory(../mpack ${CMAKE_CURRENT_BINARY_DIR}/mpack) -if(DEFINED ARDUINO) - set(PBDRV_ARDUINO true) -endif() - -include_directories(.) -add_library(pbdrv STATIC - pb-read.c - pb-write.c - ) -target_link_libraries(pbdrv - mpack - ) +# generic puzzle bus (de)serializer library +add_library(pbdrv STATIC pb-read.c pb-write.c) +target_link_libraries(pbdrv mpack) target_include_directories(pbdrv SYSTEM INTERFACE .) -list(APPEND PBDRV_SRCS pb-mod.c) - -if(PBDRV_ARDUINO) - list(APPEND PBDRV_SRCS drv/arduino/mod.cpp) -endif() - -add_library(pbdrv-mod STATIC ${PBDRV_SRCS}) +# puzzle bus module specific code (superset of pbdrv) +add_library(pbdrv-mod STATIC pb-mod.c) target_link_libraries(pbdrv-mod pbdrv) -# add_dependencies(pbdrv-mod pbdrv) - -if(PBDRV_ARDUINO) - target_link_arduino_libraries(pbdrv-mod - core - Wire - ) -endif() +target_include_directories(pbdrv-mod SYSTEM INTERFACE .) + +# supported puzzle bus drivers +include(drv/arduino/cfg.cmake) +include(drv/rp2040/cfg.cmake) diff --git a/lib/pbdrv/drv/arduino/cfg.cmake b/lib/pbdrv/drv/arduino/cfg.cmake new file mode 100644 index 0000000..36716e3 --- /dev/null +++ b/lib/pbdrv/drv/arduino/cfg.cmake @@ -0,0 +1,7 @@ +if(NOT DEFINED ARDUINO) + return() +endif() + +target_sources(pbdrv-mod PRIVATE "${CMAKE_CURRENT_LIST_DIR}/mod.cpp") +target_link_arduino_libraries(pbdrv-mod core Wire) + diff --git a/lib/pbdrv/drv/arduino/mod.h b/lib/pbdrv/drv/arduino/mod.h index e545d9b..079941a 100644 --- a/lib/pbdrv/drv/arduino/mod.h +++ b/lib/pbdrv/drv/arduino/mod.h @@ -1,7 +1,5 @@ #pragma once -#include "../../pb-mod.h" - #ifdef __cplusplus extern "C" { #endif diff --git a/lib/pbdrv/drv/rp2040/cfg.cmake b/lib/pbdrv/drv/rp2040/cfg.cmake new file mode 100644 index 0000000..0fbad18 --- /dev/null +++ b/lib/pbdrv/drv/rp2040/cfg.cmake @@ -0,0 +1,7 @@ +if(NOT PICO_PLATFORM STREQUAL "rp2040") + return() +endif() + +target_sources(pbdrv-mod PRIVATE "${CMAKE_CURRENT_LIST_DIR}/mod.c") +target_link_libraries(pbdrv-mod hardware_i2c pico_i2c_slave) + diff --git a/lib/pbdrv/drv/rp2040/mod.c b/lib/pbdrv/drv/rp2040/mod.c new file mode 100644 index 0000000..26882f7 --- /dev/null +++ b/lib/pbdrv/drv/rp2040/mod.c @@ -0,0 +1,50 @@ +#include "mod.h" + +#include "../../pb.h" +#include "../../pb-types.h" +#include "../../pb-mod.h" + +#include +#include +#include + +#define PBDRV_I2C i2c0 +#define BUF_SIZE 256 + +// NOTE: this function is called from the I2C ISR, and should return as quickly +// as possible. +static void recv_event(i2c_inst_t *i2c, i2c_slave_event_t event) { + uint8_t data[BUF_SIZE]; + size_t size = 0; + // pbdrv_i2c_recv(NULL, 0); + + switch (event) { + case I2C_SLAVE_RECEIVE: { + if (size == BUF_SIZE) return; + data[size++] = i2c_read_byte_raw(PBDRV_I2C); + break; + } + case I2C_SLAVE_FINISH: { + // TODO: handle this w/ queue mechanism instead? + pbdrv_i2c_recv(data, size); + size = 0; + break; + } + default: break; + } +} + +void pbdrv_setup() { + i2c_init(PBDRV_I2C, PB_CLOCK_SPEED_HZ); + i2c_slave_init(PBDRV_I2C, PBDRV_MOD_ADDR, &recv_event); +} + +__weak void pbdrv_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) { + i2c_set_slave_mode(PBDRV_I2C, false, PBDRV_MOD_ADDR); + + // false to write stop condition to i2c bus + i2c_write_timeout_us(PBDRV_I2C, addr, buf, sz, false, PB_TIMEOUT_US); + + i2c_set_slave_mode(PBDRV_I2C, true, PBDRV_MOD_ADDR); +} + diff --git a/lib/pbdrv/drv/rp2040/mod.h b/lib/pbdrv/drv/rp2040/mod.h new file mode 100644 index 0000000..0cf2e63 --- /dev/null +++ b/lib/pbdrv/drv/rp2040/mod.h @@ -0,0 +1,13 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +//! puzzle bus driver setup +void pbdrv_setup(); + +#ifdef __cplusplus +} +#endif + diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 4c17fba..04e612d 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -20,6 +20,7 @@ add_executable(main init.c sock.c i2c.c + mod.c ) pico_enable_stdio_usb(main 1) @@ -28,7 +29,7 @@ pico_add_extra_outputs(main) include_directories(lib/pico-sdk/lib/lwip/contrib/ports/freertos/include) -target_include_directories(main PRIVATE ${CMAKE_CURRENT_LIST_DIR}) +target_include_directories(main PRIVATE .) target_link_libraries(main pico_cyw43_arch_lwip_sys_freertos pico_stdlib diff --git a/main/config.def.h b/main/config.def.h index 11612eb..3d325fe 100644 --- a/main/config.def.h +++ b/main/config.def.h @@ -6,15 +6,15 @@ * \name Network (Wi-Fi) configuration * \{ */ -#ifndef CFG_NET_DISABLE - #ifndef CFG_NET_SSID //! network name (SSID) #define CFG_NET_SSID "" +#ifndef CFG_NET_DISABLE //! disable network communication #define CFG_NET_DISABLE #warning No SSID defined! Disabling network communication! #endif +#endif #ifndef CFG_NET_PASS //! network password @@ -31,17 +31,14 @@ #define CFG_NET_CONN_TIMEOUT 10e3 #endif +#ifdef CFG_NET_DISABLE +#undef CFG_NET_COUNTRY +#define CFG_NET_COUNTRY CYW43_COUNTRY_WORLDWIDE +#endif #ifndef CFG_NET_COUNTRY //! radio communications country #define CFG_NET_COUNTRY CYW43_COUNTRY_NETHERLANDS #endif - -#else // ifndef CFG_NET_DISABLE - -#undef CFG_NET_COUNTRY -#define CFG_NET_COUNTRY CYW43_COUNTRY_WORLDWIDE - -#endif // ifndef CFG_NET_DISABLE /** \} */ /** @@ -53,7 +50,7 @@ #define CFG_SRV_PORT 9191 #endif -#ifndef CFG_NET_DISABLE +#ifdef CFG_NET_DISABLE //! disable the i2ctcp server #define CFG_SRV_DISABLE #endif @@ -64,3 +61,12 @@ #define CFG_LED_PIN CYW43_WL_GPIO_LED_PIN #endif +#ifndef CFG_SDA_PIN +//! I^2^C SDA pin +#define CFG_SDA_PIN 16 +#endif +#ifndef CFG_SCL_PIN +//! I^2^C SCL pin +#define CFG_SCL_PIN 17 +#endif + diff --git a/main/i2c.c b/main/i2c.c index b324124..43d17bf 100644 --- a/main/i2c.c +++ b/main/i2c.c @@ -1,43 +1,14 @@ #include "i2c.h" #include "init.h" +#include "pb-mod.h" + #include #include #include #include #include -void init_i2c() { - i2c_init(I2C_PORT, 100 * 1000); // currently at 100kHz - - // Initialize I2C pins - sda(16), scl(17) - gpio_set_function(SDA_PIN, GPIO_FUNC_I2C); - gpio_set_function(SCL_PIN, GPIO_FUNC_I2C); - - gpio_pull_up(SDA_PIN); - gpio_pull_up(SCL_PIN); -} - -int read_i2c(uint8_t addr, uint8_t *output, size_t len) { - // false - finished with bus - return i2c_read_blocking (I2C_PORT, addr, output, len, false); -} - -int write_i2c(uint8_t addr, uint8_t *input, size_t len) { - // true to keep master control of bus - return i2c_write_blocking (I2C_PORT, addr, input, len, true); -} - -bool reserved_addr(uint8_t addr) { - return (addr & 0x78) == 0 || (addr & 0x78) == 0x78; -} - -void init_addr_array(uint8_t array[], int size) { - for(int i = 0; i < size; i++){ - array[i] = 0x00; - } -} - uint8_t* scan_bus(uint8_t *array) { int ret; int i = 0; @@ -46,11 +17,7 @@ uint8_t* scan_bus(uint8_t *array) { for(int addr = 0; addr < (1<<7); addr++) { // ignore reserved addresses // These are any addresses of the form 000 0xxx or 111 1xxx - if( reserved_addr(addr) ){ - ret = PICO_ERROR_GENERIC; - }else{ - ret = i2c_read_blocking(I2C_PORT, addr, &rxdata, 1, false); - } + // ret = i2c_read_blocking(I2C_PORT, addr, &rxdata, 1, false); // if acknowledged -> ret == number of bytes sent if(ret > 0){ @@ -67,27 +34,38 @@ void bus_task() { // scan bus for slaves // send updates at regular intervals await_init(); - - int i = 0; - uint8_t found[MAX_SLAVES]; - init_addr_array(found, MAX_SLAVES); - - while(1) { - // printf("Bus scan!"); - scan_bus(found); - for(int i = 0; i < MAX_SLAVES; i++){ - if( found[i] == 0x00 ) - break; - - uint8_t data = 0x01; - // send data to found slave address - write_i2c(found[i], &data, 1); + vTaskDelay(1000 / portTICK_PERIOD_MS); + + // int i = 0; + // uint8_t found[MAX_SLAVES]; + // init_addr_array(found, MAX_SLAVES); + + while (true) { + vTaskDelay(9 / portTICK_PERIOD_MS); + pbdrv_i2c_send(0x69, (uint8_t *) "bbbbbbbb", 9); - data = 0x02; - write_i2c(found[i], &data, 1); - // request update from slave addr at found[i] - //write_i2c(); - } + // i2c_write_blocking(i2c0, 0x69, (uint8_t *) "bbbbbbbb", 9, false); + // pbdrv_i2c_recv(NULL, 0); } + + // while(1) { + // // printf("Bus scan!"); + // scan_bus(found); + + // for(int i = 0; i < MAX_SLAVES; i++){ + // if( found[i] == 0x00 ) + // break; + // + // uint8_t data = 0x01; + // // send data to found slave address + // write_i2c(found[i], &data, 1); + + // data = 0x02; + // write_i2c(found[i], &data, 1); + // // request update from slave addr at found[i] + // //write_i2c(); + // } + // } } + diff --git a/main/i2c.h b/main/i2c.h index 5ad5cfb..e873fae 100644 --- a/main/i2c.h +++ b/main/i2c.h @@ -5,40 +5,8 @@ #include #include -#define SDA_PIN 16 -#define SCL_PIN 17 -#define I2C_PORT i2c0 #define MAX_SLAVES 10 -/** - * \brief initialize all required gpio for i2c usage on the pico - * - * This functions only initializes the standard gpio required to start i2c - * communications. - * - * \note Tasks shouldn't depend on any other module in the main controller - */ -void init_i2c(); - -/** - * \brief read data from addr with length len from i2c bus. - * - * This functions reads data from a specific address on the i2c bus, - * the output var will hold the data which was read from said address with - * length len. - */ -int read_i2c(uint8_t addr, uint8_t *output, size_t len); - -/** - * \brief write data to addr with length len from i2c bus. - * \param addr - * \param input - * \param len - * This functions writes data to a specific address on the i2c bus, - * the input var holds the data which will be written to the given - * address with length len. - */ -int write_i2c(uint8_t addr, uint8_t *input, size_t len); - /** \brief looking for slave addresses and requesting updates */ void bus_task(); + diff --git a/main/init.c b/main/init.c index 90f0b1e..9297093 100644 --- a/main/init.c +++ b/main/init.c @@ -1,6 +1,6 @@ #include "config.h" #include "init.h" -#include "i2c.h" +#include "drv/rp2040/mod.h" #include #include @@ -32,6 +32,14 @@ static void init_wifi() { // TODO: announce hostname(?) } +static void init_i2c() { + gpio_set_function(CFG_SDA_PIN, GPIO_FUNC_I2C); + gpio_set_function(CFG_SCL_PIN, GPIO_FUNC_I2C); + + pbdrv_setup(); + //printf("i2c setup\n"); +} + static void async_init() { init_cyw34(); init_i2c(); diff --git a/main/main.c b/main/main.c index 9fefed5..5d2abd1 100644 --- a/main/main.c +++ b/main/main.c @@ -13,10 +13,10 @@ void blink_task() { await_init(); // `blink_task` uses GPIO while (true) { - cyw43_arch_gpio_put(CFG_LED_PIN, 0); - vTaskDelay(250 / portTICK_PERIOD_MS); cyw43_arch_gpio_put(CFG_LED_PIN, 1); - vTaskDelay(250 / portTICK_PERIOD_MS); + vTaskDelay(50 / portTICK_PERIOD_MS); + cyw43_arch_gpio_put(CFG_LED_PIN, 0); + vTaskDelay(1000 / portTICK_PERIOD_MS); } } diff --git a/main/mod.c b/main/mod.c new file mode 100644 index 0000000..b34bbc9 --- /dev/null +++ b/main/mod.c @@ -0,0 +1,5 @@ +#include "pb-mod.h" + +const char * PBDRV_MOD_NAME = "main controller"; +const i2c_addr_t PBDRV_MOD_ADDR = 0x20; + -- cgit v1.2.3 From 228f50b8cb0e2bbd579cc8ae4f0a08e6d34af66e Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sun, 9 Jun 2024 10:05:07 +0200 Subject: mini cleanup --- lib/i2ctcp/CMakeLists.txt | 4 ++-- lib/i2ctcp/lib | 1 + lib/pbdrv/CMakeLists.txt | 2 +- lib/pbdrv/lib | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) create mode 120000 lib/i2ctcp/lib create mode 120000 lib/pbdrv/lib (limited to 'lib') diff --git a/lib/i2ctcp/CMakeLists.txt b/lib/i2ctcp/CMakeLists.txt index b47b1d7..956dcf7 100644 --- a/lib/i2ctcp/CMakeLists.txt +++ b/lib/i2ctcp/CMakeLists.txt @@ -6,9 +6,9 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS 1) project(i2ctcp C CXX) -add_subdirectory(../mpack ${CMAKE_CURRENT_BINARY_DIR}/mpack) +add_subdirectory(lib/mpack) -add_library(i2ctcp STATIC ./i2ctcpv1.c) +add_library(i2ctcp STATIC i2ctcpv1.c) target_link_libraries(i2ctcp mpack) target_include_directories(i2ctcp SYSTEM INTERFACE .) diff --git a/lib/i2ctcp/lib b/lib/i2ctcp/lib new file mode 120000 index 0000000..58677dd --- /dev/null +++ b/lib/i2ctcp/lib @@ -0,0 +1 @@ +../../lib \ No newline at end of file diff --git a/lib/pbdrv/CMakeLists.txt b/lib/pbdrv/CMakeLists.txt index e70cb5b..ca85b2b 100644 --- a/lib/pbdrv/CMakeLists.txt +++ b/lib/pbdrv/CMakeLists.txt @@ -10,7 +10,7 @@ add_compile_definitions(DEBUG) project(pbdrv C CXX) -add_subdirectory(../mpack ${CMAKE_CURRENT_BINARY_DIR}/mpack) +add_subdirectory(lib/mpack) # generic puzzle bus (de)serializer library add_library(pbdrv STATIC pb-read.c pb-write.c) diff --git a/lib/pbdrv/lib b/lib/pbdrv/lib new file mode 120000 index 0000000..58677dd --- /dev/null +++ b/lib/pbdrv/lib @@ -0,0 +1 @@ +../../lib \ No newline at end of file -- cgit v1.2.3 From 5fcf856a3b7482f65d2a7a152e909e1f9a304e22 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sun, 9 Jun 2024 11:59:35 +0200 Subject: fix arduino pbdrv --- lib/pbdrv/drv/arduino/mod.cpp | 2 ++ puzzle/dummy/main.cpp | 1 + puzzle/dummy/makefile | 1 + 3 files changed, 4 insertions(+) (limited to 'lib') diff --git a/lib/pbdrv/drv/arduino/mod.cpp b/lib/pbdrv/drv/arduino/mod.cpp index 518a8a4..8a38a5b 100644 --- a/lib/pbdrv/drv/arduino/mod.cpp +++ b/lib/pbdrv/drv/arduino/mod.cpp @@ -9,6 +9,7 @@ #include #include "../../pb.h" +#include "../../pb-mod.h" #include "mod.h" static void recv_event(int bytes) { @@ -31,5 +32,6 @@ __weak void pbdrv_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) { Wire.beginTransmission((int) addr); Wire.write(buf, sz); Wire.endTransmission(true); + Wire.setWireTimeout(PB_TIMEOUT_US, true); } diff --git a/puzzle/dummy/main.cpp b/puzzle/dummy/main.cpp index 4abe47a..df5b6f5 100644 --- a/puzzle/dummy/main.cpp +++ b/puzzle/dummy/main.cpp @@ -2,6 +2,7 @@ #include #include "drv/arduino/mod.h" +#include "pb-mod.h" #ifdef TEST_A #define ADDR_RX 0x69 diff --git a/puzzle/dummy/makefile b/puzzle/dummy/makefile index 041054e..509d8e3 100644 --- a/puzzle/dummy/makefile +++ b/puzzle/dummy/makefile @@ -4,6 +4,7 @@ include ../../lazy.mk export SERIAL_PORT ?= /dev/ttyACM0 flash: upload-main; +upload-main: $(TARGET) test: test_a test_b; -- cgit v1.2.3 From 4bdabb2dbf8d523e71f22f994070e99f349c2113 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sun, 9 Jun 2024 17:01:58 +0200 Subject: rp2040 driver send still working (kinda) --- lib/pbdrv/drv/rp2040/mod.c | 23 ++++++++++++++++++----- main/i2c.c | 42 +++++++++++++++++++++--------------------- main/init.c | 3 --- 3 files changed, 39 insertions(+), 29 deletions(-) (limited to 'lib') diff --git a/lib/pbdrv/drv/rp2040/mod.c b/lib/pbdrv/drv/rp2040/mod.c index 26882f7..b572c4e 100644 --- a/lib/pbdrv/drv/rp2040/mod.c +++ b/lib/pbdrv/drv/rp2040/mod.c @@ -11,12 +11,13 @@ #define PBDRV_I2C i2c0 #define BUF_SIZE 256 -// NOTE: this function is called from the I2C ISR, and should return as quickly -// as possible. +/** + * \note this function is called from the I2C ISR, and should return as quickly + * as possible. + */ static void recv_event(i2c_inst_t *i2c, i2c_slave_event_t event) { - uint8_t data[BUF_SIZE]; - size_t size = 0; - // pbdrv_i2c_recv(NULL, 0); + static uint8_t data[BUF_SIZE]; + static size_t size = 0; switch (event) { case I2C_SLAVE_RECEIVE: { @@ -39,6 +40,18 @@ void pbdrv_setup() { i2c_slave_init(PBDRV_I2C, PBDRV_MOD_ADDR, &recv_event); } +/** + * 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). + */ __weak void pbdrv_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) { i2c_set_slave_mode(PBDRV_I2C, false, PBDRV_MOD_ADDR); diff --git a/main/i2c.c b/main/i2c.c index 5db5b61..d92a93b 100644 --- a/main/i2c.c +++ b/main/i2c.c @@ -9,26 +9,26 @@ #include "i2c.h" #include "pb-mod.h" -uint8_t* scan_bus(uint8_t *array) { - int ret; - int i = 0; - uint8_t rxdata; - - for(int addr = 0; addr < (1<<7); addr++) { - // ignore reserved addresses - // These are any addresses of the form 000 0xxx or 111 1xxx - // ret = i2c_read_blocking(I2C_PORT, addr, &rxdata, 1, false); - - // if acknowledged -> ret == number of bytes sent - if(ret > 0){ - printf("found i2c slave on addr: %d\n", addr); - array[i] = addr; - i++; - } - } - - return array; -} +// uint8_t* scan_bus(uint8_t *array) { +// int ret; +// int i = 0; +// uint8_t rxdata; +// +// for(int addr = 0; addr < (1<<7); addr++) { +// // ignore reserved addresses +// // These are any addresses of the form 000 0xxx or 111 1xxx +// // ret = i2c_read_blocking(I2C_PORT, addr, &rxdata, 1, false); +// +// // if acknowledged -> ret == number of bytes sent +// if(ret > 0){ +// printf("found i2c slave on addr: %d\n", addr); +// array[i] = addr; +// i++; +// } +// } +// +// return array; +// } void bus_task() { // scan bus for slaves @@ -40,7 +40,7 @@ void bus_task() { // init_addr_array(found, MAX_SLAVES); while (true) { - vTaskDelay(9 / portTICK_PERIOD_MS); + vTaskDelay(10 / portTICK_PERIOD_MS); pbdrv_i2c_send(0x69, (uint8_t *) "bbbbbbbb", 9); // i2c_write_blocking(i2c0, 0x69, (uint8_t *) "bbbbbbbb", 9, false); diff --git a/main/init.c b/main/init.c index 1cfec9a..bd00c04 100644 --- a/main/init.c +++ b/main/init.c @@ -25,8 +25,6 @@ static void init_wifi() { if (cyw43_arch_wifi_connect_timeout_ms(CFG_NET_SSID, CFG_NET_PASS, CFG_NET_AUTH, CFG_NET_CONN_TIMEOUT)) panic("cyw43_arch_wifi_connect failed\n"); - printf("connected to Wi-Fi\n"); - // TODO: announce hostname(?) } @@ -35,7 +33,6 @@ static void init_i2c() { gpio_set_function(CFG_SCL_PIN, GPIO_FUNC_I2C); pbdrv_setup(); - //printf("i2c setup\n"); } static void async_init() { -- cgit v1.2.3 From a3ecfc2a6e6ace7bcb7666afc37ff97f9ce401b4 Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sun, 9 Jun 2024 17:37:44 +0200 Subject: WIP rp2040 pbdrv recv outside irq handler --- lib/pbdrv/drv/rp2040/mod.c | 16 +++++++++++++--- main/i2c.c | 7 ++++--- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/pbdrv/drv/rp2040/mod.c b/lib/pbdrv/drv/rp2040/mod.c index b572c4e..6becdee 100644 --- a/lib/pbdrv/drv/rp2040/mod.c +++ b/lib/pbdrv/drv/rp2040/mod.c @@ -11,13 +11,22 @@ #define PBDRV_I2C i2c0 #define BUF_SIZE 256 +static volatile bool pbdrv_i2c_msg_avail = false; +static uint8_t data[BUF_SIZE]; +static size_t size = 0; + +// TODO: create event group instead of pbdrv_i2c_msg_avail +// TODO: create freertos task that monitors the pbdrv_i2c_msg_avail flag and +// calls pbdrv_i2c_recv when a message is received + + /** * \note this function is called from the I2C ISR, and should return as quickly * as possible. */ static void recv_event(i2c_inst_t *i2c, i2c_slave_event_t event) { - static uint8_t data[BUF_SIZE]; - static size_t size = 0; + // message needs to be handled first + if (pbdrv_i2c_msg_avail) return; switch (event) { case I2C_SLAVE_RECEIVE: { @@ -27,7 +36,8 @@ static void recv_event(i2c_inst_t *i2c, i2c_slave_event_t event) { } case I2C_SLAVE_FINISH: { // TODO: handle this w/ queue mechanism instead? - pbdrv_i2c_recv(data, size); + // pbdrv_i2c_recv(data, size); + pbdrv_i2c_msg_avail = true; size = 0; break; } diff --git a/main/i2c.c b/main/i2c.c index d92a93b..8edb1e8 100644 --- a/main/i2c.c +++ b/main/i2c.c @@ -30,6 +30,10 @@ // return array; // } +void pbdrv_i2c_recv(const uint8_t * a, size_t b) { + printf("%.*s", b, a); +} + void bus_task() { // scan bus for slaves // send updates at regular intervals @@ -42,9 +46,6 @@ void bus_task() { while (true) { vTaskDelay(10 / portTICK_PERIOD_MS); pbdrv_i2c_send(0x69, (uint8_t *) "bbbbbbbb", 9); - - // i2c_write_blocking(i2c0, 0x69, (uint8_t *) "bbbbbbbb", 9, false); - // pbdrv_i2c_recv(NULL, 0); } // while(1) { -- cgit v1.2.3