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 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