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 --- main/CMakeLists.txt | 3 ++- main/compile_commands.json | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 120000 main/compile_commands.json (limited to 'main') 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 -- cgit v1.2.3 From e4b241c8ec4f12fe6ac479c2153cc540830e6a5d Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sat, 8 Jun 2024 15:38:57 +0200 Subject: clean up repository --- lazy.mk | 7 +++--- main/CMakeLists.txt | 2 ++ main/config.def.h | 69 +++++++++++++++++++++++++++++++++++++++++++++-------- main/init.c | 8 ++++--- main/main.c | 8 ++++--- main/readme.md | 24 ++++++++++++------- main/sock.c | 4 ++-- puzzle/readme.md | 13 ++++++++++ readme.md | 49 +++++++++++++++---------------------- 9 files changed, 124 insertions(+), 60 deletions(-) (limited to 'main') diff --git a/lazy.mk b/lazy.mk index 3b9813a..236aef7 100644 --- a/lazy.mk +++ b/lazy.mk @@ -1,4 +1,6 @@ -# this file is for lazy people (loek) +# NOTE: CMAKE IS THE PRIMARY BUILD SYSTEM FOR SUBFOLDERS/LIBRARIES IN THIS +# REPOSITORY. THIS FILE IS PROVIDED PURELY FOR CONVENIENCE, AND SHOULD NOT +# BECOME AN ESSENTIAL PART OF THE BUILD SYSTEM! BUILD_DIR ?= build TARGET ?= $(BUILD_DIR)/main @@ -17,12 +19,11 @@ $(BUILD_DIR)/build.ninja: CMakeLists.txt $(TARGET): $(BUILD_DIR)/build.ninja FORCE @ninja -C $(BUILD_DIR) -# ninja automatically builds in parallel, so is preferred clean: FORCE $(RM) -r $(BUILD_DIR) -# forward other targets to cmake +# Forward any unknown targets to Ninja ifneq ($(MAKECMDGOALS),) %:: @ninja -C $(BUILD_DIR) $@ diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 70cd901..4c17fba 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -9,6 +9,7 @@ include(lib/pico-sdk/pico_sdk_init.cmake) include(lib/FreeRTOS-Kernel/portable/ThirdParty/GCC/RP2040/FreeRTOS_Kernel_import.cmake) add_subdirectory(lib/mpack) add_subdirectory(lib/i2ctcp) +add_subdirectory(lib/pbdrv) project(puzzlebox_main C CXX ASM) @@ -36,5 +37,6 @@ target_link_libraries(main FreeRTOS-Kernel-Heap4 i2ctcp mpack + pbdrv-mod ) diff --git a/main/config.def.h b/main/config.def.h index 7fcaed9..11612eb 100644 --- a/main/config.def.h +++ b/main/config.def.h @@ -1,17 +1,66 @@ #pragma once #include +#include -// wifi credentials -#define CONF_NET_SSID "network name" -#define CONF_NET_PASS "network password" -#define CONF_NET_AUTH CYW43_AUTH_WPA2_AES_PSK -// max duration (milliseconds) for establishing wifi connection -#define CONF_NET_CONN_TIMEOUT 10e3 +/** + * \name Network (Wi-Fi) configuration + * \{ + */ +#ifndef CFG_NET_DISABLE -#include -#define CONF_NET_COUNTRY CYW43_COUNTRY_NETHERLANDS +#ifndef CFG_NET_SSID +//! network name (SSID) +#define CFG_NET_SSID "" +//! disable network communication +#define CFG_NET_DISABLE +#warning No SSID defined! Disabling network communication! +#endif + +#ifndef CFG_NET_PASS +//! network password +#define CFG_NET_PASS "" +#endif + +#ifndef CFG_NET_AUTH +//! network security type +#define CFG_NET_AUTH CYW43_AUTH_OPEN +#endif + +#ifndef CFG_NET_CONN_TIMEOUT +//! max duration (milliseconds) for establishing wifi connection +#define CFG_NET_CONN_TIMEOUT 10e3 +#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 +/** \} */ + +/** + * \name i2ctcp server configuration + * \{ + */ +#ifndef CFG_SRV_PORT +//! i2ctcp server port +#define CFG_SRV_PORT 9191 +#endif -#define CONF_SRV_PORT 9191 +#ifndef CFG_NET_DISABLE +//! disable the i2ctcp server +#define CFG_SRV_DISABLE +#endif +/** \} */ -#define LED_PIN CYW43_WL_GPIO_LED_PIN +#ifndef CFG_LED_PIN +//! status LED pin +#define CFG_LED_PIN CYW43_WL_GPIO_LED_PIN +#endif diff --git a/main/init.c b/main/init.c index 08177c7..90f0b1e 100644 --- a/main/init.c +++ b/main/init.c @@ -16,7 +16,7 @@ static void init_stdio() { } static void init_cyw34() { - if (cyw43_arch_init_with_country(CONF_NET_COUNTRY)) + if (cyw43_arch_init_with_country(CFG_NET_COUNTRY)) panic("cyw43_arch_init_with_country failed\n"); } @@ -24,8 +24,8 @@ static void init_wifi() { // enable 'station' mode (connect to an access point instead of acting like one) cyw43_arch_enable_sta_mode(); - // if (cyw43_arch_wifi_connect_timeout_ms(CONF_NET_SSID, CONF_NET_PASS, CONF_NET_AUTH, CONF_NET_CONN_TIMEOUT)) - // panic("cyw43_arch_wifi_connect failed\n"); + 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"); @@ -35,7 +35,9 @@ static void init_wifi() { static void async_init() { init_cyw34(); init_i2c(); +#ifndef CFG_NET_DISABLE init_wifi(); +#endif xEventGroupSetBits(init_complete, 1); diff --git a/main/main.c b/main/main.c index 19dd3cd..9fefed5 100644 --- a/main/main.c +++ b/main/main.c @@ -13,9 +13,9 @@ void blink_task() { await_init(); // `blink_task` uses GPIO while (true) { - cyw43_arch_gpio_put(LED_PIN, 0); + cyw43_arch_gpio_put(CFG_LED_PIN, 0); vTaskDelay(250 / portTICK_PERIOD_MS); - cyw43_arch_gpio_put(LED_PIN, 1); + cyw43_arch_gpio_put(CFG_LED_PIN, 1); vTaskDelay(250 / portTICK_PERIOD_MS); } } @@ -24,7 +24,9 @@ int main() { init(); xTaskCreate((TaskFunction_t) blink_task, "blink", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); - //xTaskCreate((TaskFunction_t) serve_task, "serve", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); +#ifndef CFG_SRV_DISABLE + xTaskCreate((TaskFunction_t) serve_task, "serve", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); +#endif xTaskCreate((TaskFunction_t) bus_task, "bus", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); vTaskStartScheduler(); diff --git a/main/readme.md b/main/readme.md index 425a00b..28fcfad 100644 --- a/main/readme.md +++ b/main/readme.md @@ -5,17 +5,23 @@ This directory contains the software for the main controller of the Puzzle Box. ## building 1. make sure the submodules are initialized -2. copy [`config.def.h`](./config.def.h) to `config.h` and edit the defaults -3. `mkdir build` -4. `cmake -B build` -5. `make -C build` or `ninja -C build` (choose your preference) +2. create a `config.h` file and define some options (see `config.def.h` for all + options): + ```c + #pragma once -alternatively, a makefile is provided for convenience + #define CFG_NET_SSID "network name" + #define CFG_NET_PASS "network password" + #define CFG_NET_AUTH CYW43_AUTH_WPA2_AES_PSK -## "flashing" + #include "config.def.h" + ``` +3. use CMake to build -1. [build](#building) -2. (re)connect the raspberry pi pico while holding the BOOTSEL button (this is - the only button) +## flashing + +1. build +2. hold the BOOTSEL button while resetting the pico (by power cycling or + pulling pin 30 (RUN) to GND) 3. `picotool load build/main.uf2` diff --git a/main/sock.c b/main/sock.c index fe932bb..dc3d7ea 100644 --- a/main/sock.c +++ b/main/sock.c @@ -83,10 +83,10 @@ void serve_task() { printf("starting server...\n"); struct netconn* conn = netconn_new(NETCONN_TCP); - netconn_bind(conn, IP_ADDR_ANY, CONF_SRV_PORT); + netconn_bind(conn, IP_ADDR_ANY, CFG_SRV_PORT); netconn_listen(conn); - printf("listening on %s:%d\n", ip4addr_ntoa(netif_ip4_addr(netif_list)), CONF_SRV_PORT); + printf("listening on %s:%d\n", ip4addr_ntoa(netif_ip4_addr(netif_list)), CFG_SRV_PORT); while (1) { struct netconn* incoming; if (netconn_accept(conn, &incoming) == ERR_OK) diff --git a/puzzle/readme.md b/puzzle/readme.md index 97acaf7..59c10b1 100644 --- a/puzzle/readme.md +++ b/puzzle/readme.md @@ -16,3 +16,16 @@ these subfolders, make sure you have done the following: - Install the "Arduino AVR Boards" package (1.8.6 works at the time of writing) [arduino-cmake]: https://github.com/a9183756-gh/Arduino-CMake-Toolchain + +## ESP-based puzzle modules + +### ESP-IDF SDK Setup instructions + +1. Install ESP-IDF extension in Visual Studio Code +2. Install using 'express' option +3. Install ESP-IDF v5.2.1 (release version) + + Additional help: + - [For windows](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/windows-setup.html#get-started-windows-first-steps) + - [For Linux](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html#get-started-linux-macos-first-steps) + diff --git a/readme.md b/readme.md index ac703b7..457ffaa 100644 --- a/readme.md +++ b/readme.md @@ -17,16 +17,18 @@ Please keep this repository tidy by being aware of the following conventions! ### Folder structure -|folder|contains| -|-|-| -|`/client`|Desktop PC application for controlling the puzzle box -|`/docs`|Project documentation in AsciiDoc(tor) format -|`/i2ctcp`|I2C over TCP protocol functions (used by main and client) -|`/lib`|Libraries (tracked as [submodules](#submodules)) -|`/main`|Main controller (RPi pico) software -|`/puzzle/`|Puzzle sources, each puzzle has its own subdirectory -|`/shared`|Shared code -|`/test`|Unit test framework (currently unutilized) +``` +/client desktop PC application for controlling the puzzle box +/docs project documentation in AsciiDoc(tor) format +/lib custom libraries and submodules +├───/i2ctcp I2C over TCP protocol functions (used by main and client) +├───/mpack MsgPack CMake configuration and extension +└───/pbdrv puzzle bus driver (module driver + (de)serializing functions) +/main main controller (RPi pico) software +/puzzle/ puzzle sources, each puzzle has its own subdirectory +/shared (unused) shared code +/test unit tests +``` ### Code style @@ -49,25 +51,12 @@ git submodule update --init --recursive --depth 1 until your problems go away. - - -## ESP SDK setup - -1. Install ESP-IDF extension in Visual Studio Code -2. Install using 'express' option -3. Install ESP-IDF v5.2.1 (release version) +## lazy\.mk - Additional help: - - [For windows](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/windows-setup.html#get-started-windows-first-steps) - - [For Linux](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html#get-started-linux-macos-first-steps) +[`lazy.mk`](./lazy.mk) is a file made by Loek, and includes some rules for +forwarding `make` calls to `cmake` and `ninja`. **This is purely for +convenience, and should not become an essential part of the build system**. +This file should be included at the end of a regular makefile. Any targets +defined in a makefile can be used as-is, while targets that would otherwise be +unknown will be forwarded to Ninja. -- 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 'main') 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 f6ac5839b6b54713126d430d8a037138d6619dce Mon Sep 17 00:00:00 2001 From: Loek Le Blansch Date: Sun, 9 Jun 2024 10:23:15 +0200 Subject: clean up init functions --- main/CMakeLists.txt | 2 ++ main/blink.c | 16 ++++++++++++++++ main/blink.h | 4 ++++ main/i2c.c | 12 +++++------- main/i2c.h | 6 +----- main/init.c | 19 +++++-------------- main/init.h | 29 +---------------------------- main/main.c | 24 ------------------------ main/sock.c | 2 -- main/sock.h | 2 +- main/tasks.c | 17 +++++++++++++++++ main/tasks.h | 4 ++++ 12 files changed, 56 insertions(+), 81 deletions(-) create mode 100644 main/blink.c create mode 100644 main/blink.h create mode 100644 main/tasks.c create mode 100644 main/tasks.h (limited to 'main') diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 04e612d..7a0b136 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -21,6 +21,8 @@ add_executable(main sock.c i2c.c mod.c + tasks.c + blink.c ) pico_enable_stdio_usb(main 1) diff --git a/main/blink.c b/main/blink.c new file mode 100644 index 0000000..956e910 --- /dev/null +++ b/main/blink.c @@ -0,0 +1,16 @@ +#include +#include +#include + +#include "blink.h" +#include "config.h" + +void blink_task() { + while (true) { + cyw43_arch_gpio_put(CFG_LED_PIN, 1); + vTaskDelay(50 / portTICK_PERIOD_MS); + cyw43_arch_gpio_put(CFG_LED_PIN, 0); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} + diff --git a/main/blink.h b/main/blink.h new file mode 100644 index 0000000..51c5f32 --- /dev/null +++ b/main/blink.h @@ -0,0 +1,4 @@ +#pragma once + +void blink_task(); + diff --git a/main/i2c.c b/main/i2c.c index 43d17bf..5db5b61 100644 --- a/main/i2c.c +++ b/main/i2c.c @@ -1,14 +1,14 @@ -#include "i2c.h" -#include "init.h" - -#include "pb-mod.h" - +#include +#include #include #include #include #include #include +#include "i2c.h" +#include "pb-mod.h" + uint8_t* scan_bus(uint8_t *array) { int ret; int i = 0; @@ -33,8 +33,6 @@ uint8_t* scan_bus(uint8_t *array) { void bus_task() { // scan bus for slaves // send updates at regular intervals - await_init(); - vTaskDelay(1000 / portTICK_PERIOD_MS); // int i = 0; diff --git a/main/i2c.h b/main/i2c.h index e873fae..dcc3997 100644 --- a/main/i2c.h +++ b/main/i2c.h @@ -1,12 +1,8 @@ #pragma once // https://github.com/raspberrypi/pico-examples/tree/master/i2c -#include -#include -#include - #define MAX_SLAVES 10 -/** \brief looking for slave addresses and requesting updates */ +//! looking for slave addresses and requesting updates void bus_task(); diff --git a/main/init.c b/main/init.c index 9297093..1cfec9a 100644 --- a/main/init.c +++ b/main/init.c @@ -1,15 +1,13 @@ -#include "config.h" -#include "init.h" -#include "drv/rp2040/mod.h" - #include #include -#include #include #include -EventGroupHandle_t init_complete; +#include "config.h" +#include "init.h" +#include "tasks.h" +#include "drv/rp2040/mod.h" static void init_stdio() { stdio_init_all(); @@ -46,16 +44,13 @@ static void async_init() { #ifndef CFG_NET_DISABLE init_wifi(); #endif - - xEventGroupSetBits(init_complete, 1); + init_tasks(); // delete self vTaskDelete(NULL); } void init() { - init_complete = xEventGroupCreate(); - // used for debug `printf` and `panic` on errors init_stdio(); @@ -63,7 +58,3 @@ void init() { xTaskCreate((TaskFunction_t) async_init, "init", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 4, NULL); } -void await_init() { - xEventGroupWaitBits(init_complete, 1, pdFALSE, pdFALSE, portMAX_DELAY); -} - diff --git a/main/init.h b/main/init.h index de9023c..73d2773 100644 --- a/main/init.h +++ b/main/init.h @@ -1,38 +1,11 @@ #pragma once -#include -#include - -/** - * \brief init function complete event group handle - * - * This is required to make sure the main task waits until initialization is - * complete. Due to the combination of FreeRTOS + lwIP, the initialization - * should be done while the task scheduler is running. Specifically the - * cyw43_arch_init functions make the pico hang indefinitely when used while - * the task scheduler is not running. - * - * \note `init_complete` only utilizes LSB, so `uxBitsToWaitFor` should always - * be set to *1* - */ -extern EventGroupHandle_t init_complete; - /** - * \brief initialize all peripherals on the pico + * \brief initialize the main controller * * This function only synchronously initializes the standard input/output (used * for `printf` and `panic`), and queues all other types of initialization in * the `init` task using FreeRTOS. - * - * \note Tasks dependent on the wifi being initialized should use the - * `init_complete` event group to wait for initialization to complete! */ void init(); -/** - * \brief block task until all initialization is complete - * - * utility function, see above comments - */ -void await_init(); - diff --git a/main/main.c b/main/main.c index 5d2abd1..1c615fc 100644 --- a/main/main.c +++ b/main/main.c @@ -1,34 +1,10 @@ #include #include -#include -#include - -#include "config.h" #include "init.h" -#include "sock.h" -#include "i2c.h" - -void blink_task() { - await_init(); // `blink_task` uses GPIO - - while (true) { - cyw43_arch_gpio_put(CFG_LED_PIN, 1); - vTaskDelay(50 / portTICK_PERIOD_MS); - cyw43_arch_gpio_put(CFG_LED_PIN, 0); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } -} int main() { init(); - - xTaskCreate((TaskFunction_t) blink_task, "blink", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); -#ifndef CFG_SRV_DISABLE - xTaskCreate((TaskFunction_t) serve_task, "serve", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); -#endif - xTaskCreate((TaskFunction_t) bus_task, "bus", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); - vTaskStartScheduler(); } diff --git a/main/sock.c b/main/sock.c index dc3d7ea..6a5ff72 100644 --- a/main/sock.c +++ b/main/sock.c @@ -79,8 +79,6 @@ void accept_handler(struct netconn* conn) { } void serve_task() { - await_init(); - printf("starting server...\n"); struct netconn* conn = netconn_new(NETCONN_TCP); netconn_bind(conn, IP_ADDR_ANY, CFG_SRV_PORT); diff --git a/main/sock.h b/main/sock.h index f2db35d..61828fb 100644 --- a/main/sock.h +++ b/main/sock.h @@ -3,7 +3,7 @@ #include #include -/** \brief start listening for TCP socket requests */ +//! start listening for TCP socket requests void serve_task(); void i2c_send(uint16_t addr, const char * data, size_t data_size); diff --git a/main/tasks.c b/main/tasks.c new file mode 100644 index 0000000..253c47b --- /dev/null +++ b/main/tasks.c @@ -0,0 +1,17 @@ +#include +#include + +#include "config.h" +#include "tasks.h" + +#include "blink.h" +#include "i2c.h" +#include "sock.h" + +void init_tasks() { + xTaskCreate((TaskFunction_t) blink_task, "blink", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); +#ifndef CFG_SRV_DISABLE + xTaskCreate((TaskFunction_t) serve_task, "serve", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); +#endif + xTaskCreate((TaskFunction_t) bus_task, "bus", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); +} diff --git a/main/tasks.h b/main/tasks.h new file mode 100644 index 0000000..002f830 --- /dev/null +++ b/main/tasks.h @@ -0,0 +1,4 @@ +#pragma once + +void init_tasks(); + -- 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 'main') 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 'main') 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