From 041d6d90f93bd79c5317dd7cd09761826635cdd9 Mon Sep 17 00:00:00 2001 From: indy Date: Mon, 21 Aug 2023 14:19:08 -0700 Subject: [PATCH 1/6] test code for pi <-> pico i2c --- dev/i2c-comms/pi_i2c.py | 4 ++++ dev/i2c-comms/pico_i2c.c | 12 ++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/dev/i2c-comms/pi_i2c.py b/dev/i2c-comms/pi_i2c.py index a4b07c7..02e9b31 100644 --- a/dev/i2c-comms/pi_i2c.py +++ b/dev/i2c-comms/pi_i2c.py @@ -16,3 +16,7 @@ while (True): os.write(i2c_fd, bytes(data)) time.sleep(1) + # read data from pico + incoming_data = os.read(i2c_fd, 3) # read 3 bytes + time.sleep(1) + print("Received data from Pico: ", list(incoming_data)); diff --git a/dev/i2c-comms/pico_i2c.c b/dev/i2c-comms/pico_i2c.c index 948dc18..288a15d 100644 --- a/dev/i2c-comms/pico_i2c.c +++ b/dev/i2c-comms/pico_i2c.c @@ -15,18 +15,22 @@ int main() { i2c_set_slave_mode(i2c0, true, 0x08); // i2c_set_slave_address(i2c0, 0x08); // address should match pi code - uint8_t data[3]; + uint8_t outgoing_data[3] = {0x11, 0x12, 0x13}; // example data + uint8_t incoming_data[3]; while(1) { // read data from i2c_pi.py - i2c_read_blocking(i2c0, 0x08, data, 3, true); + i2c_read_blocking(i2c0, 0x08, incoming_data, 3, true); // process data for (int i = 0; i < 3; i++) { - printf("Received data %d: 0x%02X\n ", i, data[i]); + printf("Received data %d: 0x%02X\n ", i, incoming_data[i]); } + + // send data to pi + i2c_write_blocking(i2c0, 0x08, outgoing_data, 3, true); } return 0; - + } \ No newline at end of file From fe5794f849499512251c1ec5cafc4ad939f9a4f3 Mon Sep 17 00:00:00 2001 From: indy Date: Mon, 21 Aug 2023 14:45:46 -0700 Subject: [PATCH 2/6] spi tests, have not tested them yet --- dev/i2c-comms/pi_spi.c | 57 ++++++++++++++++++++++++++++++++++++++++ dev/i2c-comms/pico_spi.c | 0 2 files changed, 57 insertions(+) create mode 100644 dev/i2c-comms/pi_spi.c create mode 100644 dev/i2c-comms/pico_spi.c diff --git a/dev/i2c-comms/pi_spi.c b/dev/i2c-comms/pi_spi.c new file mode 100644 index 0000000..6de7862 --- /dev/null +++ b/dev/i2c-comms/pi_spi.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include + +#define SPI_DEVICE "/dev/spidev0.0" +#define SPI_SPEED 1000000 // 1MHz + +int main() { + int spi_fd; + unsigned char tx_data[] = {0xAA, 0xBB, 0xCC, 0xDD}; + unsigned char rx_data[sizeof(tx_data)]; + + spi_fd = open(SPI_DEVICE, O_RDWR); + if (spi_fd < 0) { + perror("Error opening SPI device"); + return -1; + } + + int mode = SPI_MODE_0; + if (ioctl(spi_fd, SPI_IOC_WR_MODE, &mode) == -1) { + perror("Error setting SPI mode"); + return -1; + } + + if (ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &SPI_SPEED) == -1) { + perror("Error setting SPI speed"); + return -1; + } + + struct spi_ioc_transfer transfer = { + .tx_buf = (unsigned long)tx_data, + .rx_buf = (unsigned long)rx_data, + .len = sizeof(tx_data), + .speed_hz = SPI_SPEED, + .bits_per_word = 8, + }; + + while (1) { + if (ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer) == -1) { + perror("Error during SPI message transfer"); + return -1; + } + + printf("Received data: "); + for (int i = 0; i < sizeof(rx_data); i++) { + printf(" %02X", rx_data[i]); + } + printf("\n"); + sleep(1); + + } + close(spi_fd); + return 0; +} \ No newline at end of file diff --git a/dev/i2c-comms/pico_spi.c b/dev/i2c-comms/pico_spi.c new file mode 100644 index 0000000..e69de29 From df0ab2d63f415cec4173eeaf689746bb3c084a31 Mon Sep 17 00:00:00 2001 From: indy Date: Mon, 21 Aug 2023 14:49:27 -0700 Subject: [PATCH 3/6] pico spi test --- dev/i2c-comms/pico_spi.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/dev/i2c-comms/pico_spi.c b/dev/i2c-comms/pico_spi.c index e69de29..2e7be5b 100644 --- a/dev/i2c-comms/pico_spi.c +++ b/dev/i2c-comms/pico_spi.c @@ -0,0 +1,32 @@ +#include +#include "pico/stdlib.h" +#include "hardware/spi.h" + +#define SPI_PORT spi0 +#define PIN_MISO 16 +#define PIN_CS 17 + +int main() { + stdio_init_all(); + + spi_init(SPI_PORT, 1000 * 1000); // init at 1MHz + gpio_set_function(PIN_MISO, GPIO_FUNC_SPI); // set pin to SPI mode + + gpi_init(PIN_CS); + gpio_set_dir(PIN_CS, GPIO_OUT); + + while (1) { + gpio_put(PIN_CS, 1); // set CS high to indiciate start of communication + uint8_t rx_data[4]; + spi_read_blocking(SPI_PORT, 0, rx_data, sizeof(rx_data)); // read data from pi + gpio_put(PIN_CS, 0); // set CS low to indicate end of communication + + printf("Received: "); + for (int i = 0; i < sizeof(rx_data); i++) { + printf(" %02X", rx_data[i]); + } + printf("\n"); + sleep_ms(1000); + } + return 0; +} \ No newline at end of file From 6f9473ae40b25ef95e314796ba92d58ad4fe2e5a Mon Sep 17 00:00:00 2001 From: Ishan Madan <19366470+ishanm0@users.noreply.github.com> Date: Wed, 4 Oct 2023 22:37:58 -0700 Subject: [PATCH 4/6] comments/updates --- dev/i2c-comms/pi_i2c.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/i2c-comms/pi_i2c.py b/dev/i2c-comms/pi_i2c.py index 02e9b31..02250f5 100644 --- a/dev/i2c-comms/pi_i2c.py +++ b/dev/i2c-comms/pi_i2c.py @@ -4,7 +4,7 @@ I2C_PRIM = 0x0703 -# open i2c devices +# open i2c devices (sudo apt install i2c-tools) i2c_fd = os.open("/dev/i2c-1", os.O_RDWR) # set the i2c address of pico @@ -19,4 +19,4 @@ # read data from pico incoming_data = os.read(i2c_fd, 3) # read 3 bytes time.sleep(1) - print("Received data from Pico: ", list(incoming_data)); + print("Received data from Pico: ", list(incoming_data)) From fec2fbb11b6c8ec69d55664e5d1417f5b2758b79 Mon Sep 17 00:00:00 2001 From: Ishan Madan <19366470+ishanm0@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:48:41 -0700 Subject: [PATCH 5/6] experimenting (broken) --- dev/i2c-comms/pico_i2c.c | 54 ++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/dev/i2c-comms/pico_i2c.c b/dev/i2c-comms/pico_i2c.c index 288a15d..7c1222c 100644 --- a/dev/i2c-comms/pico_i2c.c +++ b/dev/i2c-comms/pico_i2c.c @@ -2,13 +2,24 @@ #include "pico/stdlib.h" #include "hardware/i2c.h" -int main() { +int main() +{ stdio_init_all(); +#ifndef PICO_DEFAULT_LED_PIN +#warning blink example requires a board with a regular LED +#else + const uint LED_PIN = PICO_DEFAULT_LED_PIN; + gpio_init(LED_PIN); + gpio_set_dir(LED_PIN, GPIO_OUT); +#endif + // init i2c at 100kHz i2c_init(i2c0, 100 * 1000); gpio_set_function(0, GPIO_FUNC_I2C); gpio_set_function(1, GPIO_FUNC_I2C); + gpio_pull_up(0); + gpio_pull_up(1); // i2c_pullup_en(i2c0, true); // set i2c address for pico @@ -18,19 +29,48 @@ int main() { uint8_t outgoing_data[3] = {0x11, 0x12, 0x13}; // example data uint8_t incoming_data[3]; - while(1) { + while (1) + { + // reset incoming data + for (int i = 0; i < 3; i++) + { + incoming_data[i] = 0x00; + } + + // if (i2c_get_read_available(i2c0) < 3) + // { + // printf("No data available\n"); + // continue; + // } + // read data from i2c_pi.py - i2c_read_blocking(i2c0, 0x08, incoming_data, 3, true); - + // i2c_read_timeout_us(i2c0, 0x0703, incoming_data, 3, false, 50000); + // i2c_read_raw_blocking(i2c0, incoming_data, 3); + int read_error = i2c_read_blocking(i2c0, 0x08, incoming_data, 3, true); + gpio_put(LED_PIN, 1); + + if (incoming_data[0] == 0x00) + { + printf("No data received %d\n", read_error); + continue; + } + + // sleep_ms(250); + // process data - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 3; i++) + { printf("Received data %d: 0x%02X\n ", i, incoming_data[i]); } // send data to pi - i2c_write_blocking(i2c0, 0x08, outgoing_data, 3, true); + int write_error = i2c_write_timeout_us(i2c0, 0x08, outgoing_data, 3, false, 50000); + printf("Write error: %d\n", write_error); + // i2c_write_raw_blocking(i2c0, outgoing_data, 3); + // i2c_write_blocking(i2c0, 0x08, outgoing_data, 3, true); + gpio_put(LED_PIN, 0); + // sleep_ms(250); } return 0; - } \ No newline at end of file From bf2198418a114dcccc05f6c2a3e2fc46ed5e7ddb Mon Sep 17 00:00:00 2001 From: Ishan Madan <19366470+ishanm0@users.noreply.github.com> Date: Thu, 5 Oct 2023 23:53:39 -0700 Subject: [PATCH 6/6] bidirectional i2c :) --- dev/i2c-comms/CMakeLists.txt | 5 +- dev/i2c-comms/pi_i2c.py | 19 +++++-- dev/i2c-comms/pico_i2c.c | 107 ++++++++++++++++++----------------- 3 files changed, 71 insertions(+), 60 deletions(-) diff --git a/dev/i2c-comms/CMakeLists.txt b/dev/i2c-comms/CMakeLists.txt index b961952..2fd69ae 100644 --- a/dev/i2c-comms/CMakeLists.txt +++ b/dev/i2c-comms/CMakeLists.txt @@ -34,7 +34,10 @@ pico_enable_stdio_usb(pico_i2c 1) # Add the standard library to the build target_link_libraries(pico_i2c - pico_stdlib) + pico_stdlib + pico_i2c_slave + hardware_i2c + ) # Add the standard include files to the build target_include_directories(pico_i2c PRIVATE diff --git a/dev/i2c-comms/pi_i2c.py b/dev/i2c-comms/pi_i2c.py index 02250f5..c912136 100644 --- a/dev/i2c-comms/pi_i2c.py +++ b/dev/i2c-comms/pi_i2c.py @@ -13,10 +13,17 @@ # send data to pico data = [0x01, 0x02, 0x03] # example data -while (True): - os.write(i2c_fd, bytes(data)) - time.sleep(1) +while True: + try: + os.write(i2c_fd, bytes(data)) + time.sleep(0.02) + print("Sent data to Pico: ", list(data)) + except OSError: + print("Remote I/O Error") # read data from pico - incoming_data = os.read(i2c_fd, 3) # read 3 bytes - time.sleep(1) - print("Received data from Pico: ", list(incoming_data)) + try: + incoming_data = os.read(i2c_fd, 3) # read 3 bytes + time.sleep(0.02) + print("Received data from Pico: ", list(incoming_data)) + except TimeoutError: + print("Timeout Error") diff --git a/dev/i2c-comms/pico_i2c.c b/dev/i2c-comms/pico_i2c.c index 7c1222c..3880f90 100644 --- a/dev/i2c-comms/pico_i2c.c +++ b/dev/i2c-comms/pico_i2c.c @@ -1,15 +1,63 @@ #include -#include "pico/stdlib.h" -#include "hardware/i2c.h" +#include +#include +#include + +#ifndef PICO_DEFAULT_LED_PIN +#warning blink requires a board with a regular LED +#else +const uint LED_PIN = PICO_DEFAULT_LED_PIN; +#endif + +uint8_t outgoing_data[3] = {0x11, 0x12, 0x13}; // example data +uint8_t incoming_data[3]; +int data_index = 0; + +static void i2c_slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) +{ + switch (event) + { + case I2C_SLAVE_RECEIVE: // master has written some data + for (int i = 0; i < 3; i++) + { + if (incoming_data[i] == 0x00) + { + incoming_data[i] = i2c_read_byte_raw(i2c); + printf("Received data %d: 0x%02X\n ", i, incoming_data[i]); + gpio_put(LED_PIN, 1); + break; + } + } + break; + case I2C_SLAVE_REQUEST: // master is requesting data + i2c_write_byte_raw(i2c, outgoing_data[data_index]); + printf("Sent data %d: 0x%02X\n ", data_index, outgoing_data[data_index]); + gpio_put(LED_PIN, 0); + data_index++; + if (data_index > 2) + { + data_index = 0; + } + break; + case I2C_SLAVE_FINISH: // master has signalled Stop / Restart + data_index = 0; + for (int i = 0; i < 3; i++) + { + incoming_data[i] = 0x00; + } + break; + default: + break; + } +} int main() { stdio_init_all(); #ifndef PICO_DEFAULT_LED_PIN -#warning blink example requires a board with a regular LED +#warning blink requires a board with a regular LED #else - const uint LED_PIN = PICO_DEFAULT_LED_PIN; gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); #endif @@ -18,59 +66,12 @@ int main() i2c_init(i2c0, 100 * 1000); gpio_set_function(0, GPIO_FUNC_I2C); gpio_set_function(1, GPIO_FUNC_I2C); - gpio_pull_up(0); - gpio_pull_up(1); - // i2c_pullup_en(i2c0, true); // set i2c address for pico - i2c_set_slave_mode(i2c0, true, 0x08); - // i2c_set_slave_address(i2c0, 0x08); // address should match pi code - - uint8_t outgoing_data[3] = {0x11, 0x12, 0x13}; // example data - uint8_t incoming_data[3]; + i2c_slave_init(i2c0, 0x08, &i2c_slave_handler); while (1) - { - // reset incoming data - for (int i = 0; i < 3; i++) - { - incoming_data[i] = 0x00; - } - - // if (i2c_get_read_available(i2c0) < 3) - // { - // printf("No data available\n"); - // continue; - // } - - // read data from i2c_pi.py - // i2c_read_timeout_us(i2c0, 0x0703, incoming_data, 3, false, 50000); - // i2c_read_raw_blocking(i2c0, incoming_data, 3); - int read_error = i2c_read_blocking(i2c0, 0x08, incoming_data, 3, true); - gpio_put(LED_PIN, 1); - - if (incoming_data[0] == 0x00) - { - printf("No data received %d\n", read_error); - continue; - } - - // sleep_ms(250); - - // process data - for (int i = 0; i < 3; i++) - { - printf("Received data %d: 0x%02X\n ", i, incoming_data[i]); - } - - // send data to pi - int write_error = i2c_write_timeout_us(i2c0, 0x08, outgoing_data, 3, false, 50000); - printf("Write error: %d\n", write_error); - // i2c_write_raw_blocking(i2c0, outgoing_data, 3); - // i2c_write_blocking(i2c0, 0x08, outgoing_data, 3, true); - gpio_put(LED_PIN, 0); - // sleep_ms(250); - } + ; return 0; } \ No newline at end of file