From e3e8c7c1a303d0427fdfae1e5cfe6d29cf7d3feb Mon Sep 17 00:00:00 2001 From: SEEK-THE-VOID-LIGHT Date: Wed, 21 Jul 2021 00:22:45 +0200 Subject: [PATCH 1/2] Added example slave_mode for i2c --- i2c/CMakeLists.txt | 1 + i2c/slave_mode/CMakeLists.txt | 8 ++ i2c/slave_mode/main.c | 112 +++++++++++++++++++++++++++ i2c/slave_mode/pico_sdk_import.cmake | 62 +++++++++++++++ 4 files changed, 183 insertions(+) create mode 100644 i2c/slave_mode/CMakeLists.txt create mode 100644 i2c/slave_mode/main.c create mode 100644 i2c/slave_mode/pico_sdk_import.cmake diff --git a/i2c/CMakeLists.txt b/i2c/CMakeLists.txt index 080153f49..a5572d6e6 100644 --- a/i2c/CMakeLists.txt +++ b/i2c/CMakeLists.txt @@ -2,4 +2,5 @@ if (NOT PICO_NO_HARDWARE) add_subdirectory(bus_scan) add_subdirectory(lcd_1602_i2c) add_subdirectory(mpu6050_i2c) + add_subdirectory(slave_mode) endif () diff --git a/i2c/slave_mode/CMakeLists.txt b/i2c/slave_mode/CMakeLists.txt new file mode 100644 index 000000000..1a4636271 --- /dev/null +++ b/i2c/slave_mode/CMakeLists.txt @@ -0,0 +1,8 @@ +add_executable(i2c_slave_mode main.c) + +target_link_libraries(i2c_slave_mode pico_stdlib hardware_gpio hardware_i2c) + +pico_enable_stdio_usb(i2c_slave_mode 1) +pico_enable_stdio_uart(i2c_slave_mode 0) + +pico_add_extra_outputs(i2c_slave_mode) diff --git a/i2c/slave_mode/main.c b/i2c/slave_mode/main.c new file mode 100644 index 000000000..163aac6b1 --- /dev/null +++ b/i2c/slave_mode/main.c @@ -0,0 +1,112 @@ +#include +#include +#include "pico/stdlib.h" +#include "hardware/gpio.h" +#include "hardware/i2c.h" + +#define bus i2c0 +#define SDA 16 +#define SCL 17 +#define FIFO_SIZE 16 + +/** + * @brief initialize i2c bus on specified address + * + * @param address slave address (0x21 seems to be causing problem for some reasons I cannot understand) + */ +void init_i2c_bus(uint8_t address) { + i2c_init(bus, 100000); // BUS SPEED IS 400kHz, Clock Stretching is enabled + gpio_set_function(SCL, GPIO_FUNC_I2C); + gpio_set_function(SDA, GPIO_FUNC_I2C); + gpio_pull_up(SDA); + gpio_pull_up(SCL); + i2c_set_slave_mode(bus, true, address); +} + + +/** + * @brief Listen for i²c commands in the RX FIFO. Wait until transmit from master side is finished. + * + * @param i2c i2c instance + * @param handler_function function to handle the 16 byte message that the slave can read + */ +void i2c_listener(i2c_inst_t *i2c, void (*handler_function)(i2c_inst_t*, uint8_t*)) { + uint8_t buffer[FIFO_SIZE]; + memset(buffer, 0, FIFO_SIZE); + int available; + + for( ;; ) { + available = i2c_get_read_available(i2c); + + if( available > 0 ) { + + int old_available; + do { + old_available = available; + sleep_us(100); + available = i2c_get_read_available(i2c); + } while( available != old_available ); + + // read and execute handler function + i2c_read_raw_blocking(i2c, buffer, available); + handler_function(i2c, buffer); + memset(buffer, 0, FIFO_SIZE); + } + } +} + +/** + * @brief Handler function called from the listener + * + * @param i2c i2c instance + * @param message 16 byte i2c message, the first byte is assumed to be the command byte + */ +void on_message(i2c_inst_t *i2c, uint8_t *message) { + printf("\nRECEIVED MESSAGE\n"); + printf("----------PAYLOAD--------------\n"); + for( int i = 0; i < FIFO_SIZE; i++ ) { + printf("%02x ", message[i]); + } + printf("\n-------------------------------\n"); + + // check the first byte in command for command type + switch( message[0] ) { // handle commands in the array + + // TOGGLE LED + case 0x10: + printf("LED SIGNAL!!!\n"); + gpio_put(25, !gpio_get(25)); + break; + + // ECHO SOME BYTES BACK TO MASTER + case 0x20: + printf("ECHO SIGNAL!!!\n"); + const uint8_t buffer[2] = {0x20,0x30}; + i2c_write_raw_blocking(i2c0, buffer, 2); + break; + + // NONE OF THE COMMAND BYTES APPLY + default: + printf("NO MATCHING COMMAND\n"); + break; + } +} + +int main() { + + // STDOUT over usb serial + stdio_usb_init(); + + // set address 0x31 + init_i2c_bus(0x31); + + // setup LED + gpio_init(25); + gpio_set_dir(25, GPIO_OUT); + + // start listener. This can be launched in a second core if neccecary + // connect i2c num and handler function + i2c_listener(bus, on_message); + + return 0; +} diff --git a/i2c/slave_mode/pico_sdk_import.cmake b/i2c/slave_mode/pico_sdk_import.cmake new file mode 100644 index 000000000..28efe9eab --- /dev/null +++ b/i2c/slave_mode/pico_sdk_import.cmake @@ -0,0 +1,62 @@ +# This is a copy of /external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + FetchContent_Populate(pico_sdk) + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) From f46a3f1f4db0e76d7f07d0a0c1c5a60f2e17eb8c Mon Sep 17 00:00:00 2001 From: SEEK-THE-VOID-LIGHT Date: Wed, 21 Jul 2021 00:22:59 +0200 Subject: [PATCH 2/2] Added example slave_mode for i2c --- i2c/slave_mode/pico_sdk_import.cmake | 62 ---------------------------- 1 file changed, 62 deletions(-) delete mode 100644 i2c/slave_mode/pico_sdk_import.cmake diff --git a/i2c/slave_mode/pico_sdk_import.cmake b/i2c/slave_mode/pico_sdk_import.cmake deleted file mode 100644 index 28efe9eab..000000000 --- a/i2c/slave_mode/pico_sdk_import.cmake +++ /dev/null @@ -1,62 +0,0 @@ -# This is a copy of /external/pico_sdk_import.cmake - -# This can be dropped into an external project to help locate this SDK -# It should be include()ed prior to project() - -if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) - set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) - message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") -endif () - -if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) - set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) - message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") -endif () - -if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) - set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) - message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") -endif () - -set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") -set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") -set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") - -if (NOT PICO_SDK_PATH) - if (PICO_SDK_FETCH_FROM_GIT) - include(FetchContent) - set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) - if (PICO_SDK_FETCH_FROM_GIT_PATH) - get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") - endif () - FetchContent_Declare( - pico_sdk - GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk - GIT_TAG master - ) - if (NOT pico_sdk) - message("Downloading Raspberry Pi Pico SDK") - FetchContent_Populate(pico_sdk) - set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) - endif () - set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) - else () - message(FATAL_ERROR - "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." - ) - endif () -endif () - -get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") -if (NOT EXISTS ${PICO_SDK_PATH}) - message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") -endif () - -set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) -if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) - message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") -endif () - -set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) - -include(${PICO_SDK_INIT_CMAKE_FILE})