Skip to content

Add example for slave mode operation with the Pi Pico #145

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions i2c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 ()
8 changes: 8 additions & 0 deletions i2c/slave_mode/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
112 changes: 112 additions & 0 deletions i2c/slave_mode/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include <stdio.h>
#include <string.h>
#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;
}