> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 40 Pin Low Speed Connector

The Dragonwing IQ9-EVK contains one low-speed connector (JLS1) that provides access to various GPIOs, CAN, QUPs, and other interfaces.

## Pinout

The figure below shows the default functions of the IQ-9075 EVK 40-pin LS connector.

<img src="https://mintcdn.com/qualcomm-prod/tRWO8v_Df_ujnDuD/Ubuntu/images/peripheral-interfaces/40-pin-LS-details.png?fit=max&auto=format&n=tRWO8v_Df_ujnDuD&q=85&s=28cc57f0e3d27c4f6c488d8d842dd73e" width="1639" height="1050" data-path="Ubuntu/images/peripheral-interfaces/40-pin-LS-details.png" />

<img src="https://mintcdn.com/qualcomm-prod/P0rmO3AZfXx7cgqQ/Ubuntu/images/peripheral-interfaces/LS-connector-functional_details.png?fit=max&auto=format&n=P0rmO3AZfXx7cgqQ&q=85&s=4b2f5975235f681668b56d5143d846d2" width="1449" height="834" data-path="Ubuntu/images/peripheral-interfaces/LS-connector-functional_details.png" />

## GPIOs

<Note>
  The following commands require root privileges. Use `sudo su` to switch to the root user.
</Note>

### Identify GPIO Subsystem Numbers

Identify the base GPIO number by running the following command and looking for `platform/f000000.pinctrl` (gpiochip4). For IQ-9075, the base is **560**.

```bash theme={null}
cat /sys/kernel/debug/gpio
```

**Example:** For LS connector Pin 5, GPIO number is 54. The GPIO subsystem number is: 560 + 54 = **614**.

<img src="https://mintcdn.com/qualcomm-prod/P0rmO3AZfXx7cgqQ/Ubuntu/images/peripheral-interfaces/LS-connector-subsystem_gpio.png?fit=max&auto=format&n=P0rmO3AZfXx7cgqQ&q=85&s=25c504c2b3fc0bfeecbdcec045fec543" width="921" height="893" data-path="Ubuntu/images/peripheral-interfaces/LS-connector-subsystem_gpio.png" />

### Control GPIOs via sysfs

<Steps>
  <Step title="Export the GPIO">
    ```bash theme={null}
    cd /sys/class/gpio
    echo 614 > export
    ```
  </Step>

  <Step title="Configure direction and value">
    ```bash theme={null}
    cd gpio614
    echo out > direction
    echo 1 > value
    ```

    | Attribute   | Values                              |
    | ----------- | ----------------------------------- |
    | `direction` | `in` (input), `out` (output)        |
    | `value`     | `0` (low), `1` (high)               |
    | `edge`      | `rising`, `falling`, `both`, `none` |
  </Step>

  <Step title="Unexport when done">
    ```bash theme={null}
    cd ..
    echo 614 > unexport
    ```
  </Step>
</Steps>

### GPIO Code Examples

<Tabs>
  <Tab title="C">
    The following example sets pin 5 as output, pin 7 as input, and loops to check the level of pin 7.

    ```c theme={null}
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    int out_gpio = 614;
    int in_gpio = 615;

    int main() {
        char export_path[50] = {};
        char export_command[100] = {};
        snprintf(export_path, sizeof(export_path), "/sys/class/gpio/export");
        snprintf(export_command, sizeof(export_command), "echo %d > %s ", out_gpio, export_path);
        system(export_command);
        snprintf(export_command, sizeof(export_command), "echo %d > %s ", in_gpio, export_path);
        system(export_command);

        char direction_path[50] = {};
        snprintf(direction_path, sizeof(direction_path), "/sys/class/gpio/gpio%d/direction", out_gpio);
        FILE *direction_file = fopen(direction_path, "w");
        if (direction_file == NULL) { perror("Failed to open GPIO direction file"); return -1; }
        fprintf(direction_file, "out");
        fclose(direction_file);

        snprintf(direction_path, sizeof(direction_path), "/sys/class/gpio/gpio%d/direction", in_gpio);
        direction_file = fopen(direction_path, "w");
        if (direction_file == NULL) { perror("Failed to open GPIO direction file"); return -1; }
        fprintf(direction_file, "in");
        fclose(direction_file);

        char value_in_path[50] = {};
        char value_out_path[50] = {};
        char cat_command[100] = {};
        snprintf(value_out_path, sizeof(value_out_path), "/sys/class/gpio/gpio%d/value", out_gpio);
        snprintf(value_in_path, sizeof(value_in_path), "/sys/class/gpio/gpio%d/value", in_gpio);
        snprintf(cat_command, sizeof(cat_command), "cat %s", value_in_path);

        FILE *value_out_file = fopen(value_out_path, "w");
        if (value_out_file == NULL) { perror("Failed to open GPIO value file"); return -1; }

        for (int i = 0; i < 5; i++) {
            fprintf(value_out_file, "1"); fflush(value_out_file);
            system(cat_command); sleep(1);
            fprintf(value_out_file, "0"); fflush(value_out_file);
            system(cat_command); sleep(1);
        }
        fclose(value_out_file);

        char unexport_path[50] = {};
        char unexport_command[100] = {};
        snprintf(unexport_path, sizeof(unexport_path), "/sys/class/gpio/unexport");
        snprintf(unexport_command, sizeof(unexport_command), "echo %d > %s ", out_gpio, unexport_path);
        system(unexport_command);
        snprintf(unexport_command, sizeof(unexport_command), "echo %d > %s ", in_gpio, unexport_path);
        system(unexport_command);
        return 0;
    }
    ```

    <Steps>
      <Step title="Compile">
        ```bash theme={null}
        gcc gpio.c -o gpio
        ```
      </Step>

      <Step title="Connect pins">
        Short pin 5 and pin 7 with a Dupont wire.

        <img src="https://mintcdn.com/qualcomm-prod/P0rmO3AZfXx7cgqQ/Ubuntu/images/peripheral-interfaces/IQ9075_short_pin5_7_gpio_test.png?fit=max&auto=format&n=P0rmO3AZfXx7cgqQ&q=85&s=fae828e0e3c820084ca21a0994c7b845" width="520" height="584" data-path="Ubuntu/images/peripheral-interfaces/IQ9075_short_pin5_7_gpio_test.png" />

        <Warning>
          Pay attention to pin order. Do not short power and ground pins — this may damage the board.
        </Warning>
      </Step>

      <Step title="Run">
        ```bash theme={null}
        ./gpio
        ```

        <img src="https://mintcdn.com/qualcomm-prod/tRWO8v_Df_ujnDuD/Ubuntu/images/peripheral-interfaces/IQ9075-GPIO_testing_C_code.png?fit=max&auto=format&n=tRWO8v_Df_ujnDuD&q=85&s=8368ca3369e594c4b576a2224675f2f6" width="801" height="252" data-path="Ubuntu/images/peripheral-interfaces/IQ9075-GPIO_testing_C_code.png" />
      </Step>
    </Steps>
  </Tab>

  <Tab title="Python">
    Install `python3-periphery`:

    ```bash theme={null}
    apt install python3-pip
    apt install python3-periphery
    ```

    The following example sets pin 5 as output, pin 7 as input, and loops to check the level of pin 7.

    ```python theme={null}
    from periphery import GPIO
    import time

    out_gpio = GPIO(614, "out")
    in_gpio = GPIO(615, "in")

    try:
        while True:
            try:
                out_gpio.write(True)
                print(f"in_gpio level: {in_gpio.read()}")
                out_gpio.write(False)
                print(f"in_gpio level: {in_gpio.read()}")
                time.sleep(1)
            except KeyboardInterrupt:
                out_gpio.write(False)
                break
    except IOError:
        print("Error")
    finally:
        out_gpio.close()
        in_gpio.close()
    ```

    <Steps>
      <Step title="Connect pins">
        Short pin 5 and pin 7 with a Dupont wire.

        <img src="https://mintcdn.com/qualcomm-prod/P0rmO3AZfXx7cgqQ/Ubuntu/images/peripheral-interfaces/IQ9075_short_pin5_7_gpio_test.png?fit=max&auto=format&n=P0rmO3AZfXx7cgqQ&q=85&s=fae828e0e3c820084ca21a0994c7b845" width="520" height="584" data-path="Ubuntu/images/peripheral-interfaces/IQ9075_short_pin5_7_gpio_test.png" />

        <Warning>
          Pay attention to pin order. Do not short power and ground pins — this may damage the board.
        </Warning>
      </Step>

      <Step title="Run">
        ```bash theme={null}
        python3 gpio.py
        ```

        <img src="https://mintcdn.com/qualcomm-prod/tRWO8v_Df_ujnDuD/Ubuntu/images/peripheral-interfaces/IQ9075-GPIO_testing_python_code.png?fit=max&auto=format&n=tRWO8v_Df_ujnDuD&q=85&s=93ba8ab3b4f6747b843f65002de0fa8a" width="603" height="485" data-path="Ubuntu/images/peripheral-interfaces/IQ9075-GPIO_testing_python_code.png" />
      </Step>
    </Steps>
  </Tab>
</Tabs>

## UART

Pins 5 and 7 are configured for UART by default (GPIO lines 54 and 55, mapping to `uart12 = qup1_se5 (0xa98000)`).

Follow the [Modify serial engine node](./peripheral_interface_overview#modify-serial-engine-node) procedure to enable the UART interface. After enabling, the device node appears at `/dev/ttyHS3`.

```bash theme={null}
ubuntu@ubuntu:/dev$ ls -al ttyHS3
crw-rw---- 1 root dialout 236, 2 Nov 25 18:16 ttyHS3
```

<Tabs>
  <Tab title="Shell">
    <Steps>
      <Step title="Connect pins">
        Short pin 5 and pin 7 with a Dupont wire.

        <img src="https://mintcdn.com/qualcomm-prod/P0rmO3AZfXx7cgqQ/Ubuntu/images/peripheral-interfaces/IQ9075_short_pin5_7_gpio_test.png?fit=max&auto=format&n=P0rmO3AZfXx7cgqQ&q=85&s=fae828e0e3c820084ca21a0994c7b845" width="520" height="584" data-path="Ubuntu/images/peripheral-interfaces/IQ9075_short_pin5_7_gpio_test.png" />

        <Warning>
          Pay attention to pin order. Do not short power and ground pins — this may damage the board.
        </Warning>
      </Step>

      <Step title="Configure UART">
        ```bash theme={null}
        sudo stty -F /dev/ttyHS3 ispeed 115200 ospeed 115200
        sudo stty -F /dev/ttyHS3 115200 -echo -icanon -isig -iexten -icrnl -ixon -opost
        ```
      </Step>

      <Step title="Open two SSH terminals">
        **Terminal 1 (RX):**

        ```bash theme={null}
        sudo cat /dev/ttyHS3
        ```

        **Terminal 2 (TX):**

        ```bash theme={null}
        sudo su
        echo "hello world!" > /dev/ttyHS3
        ```

        <img src="https://mintcdn.com/qualcomm-prod/P0rmO3AZfXx7cgqQ/Ubuntu/images/peripheral-interfaces/IQ9075_UART_loopbacktest.png?fit=max&auto=format&n=P0rmO3AZfXx7cgqQ&q=85&s=b2b4a5cd8f092adca217eeddbd763eb1" width="1354" height="217" data-path="Ubuntu/images/peripheral-interfaces/IQ9075_UART_loopbacktest.png" />
      </Step>
    </Steps>
  </Tab>

  <Tab title="C">
    The following C program sends and receives data over UART with full raw-mode configuration and optional PM clock vote support.

    ```c theme={null}
    #define _GNU_SOURCE
    #include <errno.h>
    #include <fcntl.h>
    #include <getopt.h>
    #include <poll.h>
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <termios.h>
    #include <unistd.h>
    #include <sys/ioctl.h>

    #ifndef TIOCPMGET
    #define TIOCPMGET  0x544D
    #endif
    #ifndef TIOCPMPUT
    #define TIOCPMPUT  0x544E
    #endif

    static volatile sig_atomic_t g_stop = 0;
    static void on_sigint(int sig) { (void)sig; g_stop = 1; }

    static speed_t baud_to_speed(int baud) {
        switch (baud) {
            case 9600:   return B9600;
            case 19200:  return B19200;
            case 38400:  return B38400;
            case 57600:  return B57600;
            case 115200: return B115200;
            case 230400: return B230400;
            default:     return 0;
        }
    }

    static void uart_clock_vote_on(int fd) {
        if (ioctl(fd, TIOCPMGET, 0) < 0 && errno != ENOTTY)
            fprintf(stderr, "WARN: ioctl(TIOCPMGET) failed: %s\n", strerror(errno));
    }

    static void uart_clock_vote_off(int fd) {
        if (ioctl(fd, TIOCPMPUT, 0) < 0 && errno != ENOTTY)
            fprintf(stderr, "WARN: ioctl(TIOCPMPUT) failed: %s\n", strerror(errno));
    }

    static int configure_serial(int fd, int baud, int rx_block_forever) {
        struct termios tty;
        if (tcgetattr(fd, &tty) != 0) { perror("tcgetattr"); return -1; }
        cfmakeraw(&tty);
        speed_t spd = baud_to_speed(baud);
        if (spd == 0) { fprintf(stderr, "Unsupported baud rate: %d\n", baud); return -1; }
        cfsetispeed(&tty, spd); cfsetospeed(&tty, spd);
        tty.c_cflag &= ~(PARENB | CSTOPB | CSIZE); tty.c_cflag |= CS8 | CLOCAL | CREAD | ~CRTSCTS;
        tty.c_iflag &= ~(IXON | IXOFF | IXANY);
        tty.c_cc[VMIN]  = rx_block_forever ? 1 : 0;
        tty.c_cc[VTIME] = 0;
        if (tcsetattr(fd, TCSANOW, &tty) != 0) { perror("tcsetattr"); return -1; }
        tcflush(fd, TCIOFLUSH);
        return 0;
    }

    int main(int argc, char **argv) {
        struct sigaction sa; memset(&sa, 0, sizeof(sa));
        sa.sa_handler = on_sigint; sigaction(SIGINT, &sa, NULL);

        const char *device = "/dev/ttyHS3";
        int baud = 115200, rx_mode = 0;
        const char *tx = "hello world!\n";

        int c;
        while ((c = getopt(argc, argv, "d:b:t:Rh")) != -1) {
            switch (c) {
                case 'd': device = optarg; break;
                case 'b': baud = atoi(optarg); break;
                case 't': tx = optarg; break;
                case 'R': rx_mode = 1; break;
            }
        }

        int fd = open(device, O_RDWR | O_NOCTTY);
        if (fd < 0) { fprintf(stderr, "Failed to open %s: %s\n", device, strerror(errno)); return 1; }
        if (configure_serial(fd, baud, rx_mode) != 0) { close(fd); return 1; }

        if (rx_mode) {
            struct pollfd pfd = { .fd = fd, .events = POLLIN };
            uart_clock_vote_on(fd);
            printf("RX: waiting on %s (Ctrl+C to stop)...\n", device);
            while (!g_stop) {
                if (poll(&pfd, 1, -1) < 0) { if (errno == EINTR) continue; break; }
                if (pfd.revents & POLLIN) {
                    unsigned char buf[512];
                    ssize_t r = read(fd, buf, sizeof(buf));
                    if (r > 0) { fwrite(buf, 1, r, stdout); fflush(stdout); }
                }
            }
            uart_clock_vote_off(fd);
        } else {
            uart_clock_vote_on(fd);
            ssize_t w = write(fd, tx, strlen(tx));
            printf("TX (%zd bytes) on %s: %s", w, device, tx);
            uart_clock_vote_off(fd);
        }
        close(fd);
        return 0;
    }
    ```

    <Steps>
      <Step title="Compile">
        ```bash theme={null}
        gcc -O2 -Wall -o uarttest uart.c
        ```
      </Step>

      <Step title="Open two SSH terminals">
        **Terminal 1 (RX):**

        ```bash theme={null}
        sudo ./uarttest --rx -b 115200 -d /dev/ttyHS3
        ```

        **Terminal 2 (TX):**

        ```bash theme={null}
        sudo ./uarttest -b 115200 -d /dev/ttyHS3 -t $'UART test\n'
        ```

        <img src="https://mintcdn.com/qualcomm-prod/P0rmO3AZfXx7cgqQ/Ubuntu/images/peripheral-interfaces/IQ9075_UART_loopbacktest_C.png?fit=max&auto=format&n=P0rmO3AZfXx7cgqQ&q=85&s=832c19a46e7401548ea9920193e17f4d" width="1528" height="158" data-path="Ubuntu/images/peripheral-interfaces/IQ9075_UART_loopbacktest_C.png" />
      </Step>
    </Steps>
  </Tab>

  <Tab title="Python">
    The following Python script sends and receives data over UART using raw termios configuration.

    ```python theme={null}
    #!/usr/bin/env python3
    import argparse, errno, fcntl, os, select, signal, sys, termios

    TIOCPMGET = 0x544D
    TIOCPMPUT = 0x544E
    STOP = False

    def sigint_handler(signum, frame):
        global STOP
        STOP = True

    signal.signal(signal.SIGINT, sigint_handler)

    def vote_clock_on(fd):
        try: fcntl.ioctl(fd, TIOCPMGET, 0)
        except OSError as e:
            if e.errno != errno.ENOTTY: print(f"WARN: {e}", file=sys.stderr)

    def vote_clock_off(fd):
        try: fcntl.ioctl(fd, TIOCPMPUT, 0)
        except OSError as e:
            if e.errno != errno.ENOTTY: print(f"WARN: {e}", file=sys.stderr)

    def set_raw_8n1(fd, baud, rx_block_forever):
        attrs = termios.tcgetattr(fd)
        iflag, oflag, cflag, lflag, ispeed, ospeed, cc = attrs
        iflag &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK | termios.ISTRIP |
                   termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IXON | termios.IXOFF | termios.IXANY)
        oflag &= ~termios.OPOST
        lflag &= ~(termios.ECHO | termios.ECHONL | termios.ICANON | termios.ISIG | termios.IEXTEN)
        cflag &= ~(termios.CSIZE | termios.PARENB | termios.CSTOPB)
        cflag |= termios.CS8 | termios.CREAD | termios.CLOCAL
        if hasattr(termios, "CRTSCTS"): cflag &= ~termios.CRTSCTS
        baud_map = {9600: termios.B9600, 19200: termios.B19200, 38400: termios.B38400,
                    57600: termios.B57600, 115200: termios.B115200, 230400: termios.B230400}
        if baud not in baud_map: raise ValueError(f"Unsupported baud rate: {baud}")
        ispeed = ospeed = baud_map[baud]
        cc[termios.VMIN] = 1 if rx_block_forever else 0
        cc[termios.VTIME] = 0
        termios.tcsetattr(fd, termios.TCSANOW, [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
        termios.tcflush(fd, termios.TCIOFLUSH)

    def rx_forever(fd, device):
        vote_clock_on(fd)
        print(f"RX: waiting on {device} (Ctrl+C to stop)...")
        while not STOP:
            rlist, _, _ = select.select([fd], [], [], 1.0)
            if rlist:
                data = os.read(fd, 512)
                if data: sys.stdout.buffer.write(data); sys.stdout.buffer.flush()
        vote_clock_off(fd)
        print("\nRX: stopped.")

    def tx_once(fd, device, payload):
        vote_clock_on(fd)
        n = os.write(fd, payload)
        sys.stdout.write(f"TX ({n} bytes) on {device}: ")
        sys.stdout.buffer.write(payload); sys.stdout.buffer.flush()
        vote_clock_off(fd)

    def main():
        p = argparse.ArgumentParser()
        p.add_argument("-d", "--device", default="/dev/ttyHS3")
        p.add_argument("-b", "--baud", type=int, default=115200)
        p.add_argument("-t", "--tx", default="hello world!\n")
        p.add_argument("-R", "--rx", action="store_true")
        args = p.parse_args()
        fd = os.open(args.device, os.O_RDWR | os.O_NOCTTY)
        set_raw_8n1(fd, args.baud, rx_block_forever=args.rx)
        if args.rx: rx_forever(fd, args.device)
        else: tx_once(fd, args.device, args.tx.encode("utf-8", errors="replace"))
        os.close(fd)

    if __name__ == "__main__":
        raise SystemExit(main())
    ```

    <Steps>
      <Step title="Open two SSH terminals">
        **Terminal 1 (RX):**

        ```bash theme={null}
        sudo python3 uart_tool.py --rx -b 115200
        ```

        **Terminal 2 (TX):**

        ```bash theme={null}
        sudo python3 uart_tool.py -b 115200 -t $'UART test\n'
        ```

        <img src="https://mintcdn.com/qualcomm-prod/P0rmO3AZfXx7cgqQ/Ubuntu/images/peripheral-interfaces/IQ9075_UART_loopbacktest_python.png?fit=max&auto=format&n=P0rmO3AZfXx7cgqQ&q=85&s=3230d11e1adf69910a1d17a5fa88353b" width="1571" height="156" data-path="Ubuntu/images/peripheral-interfaces/IQ9075_UART_loopbacktest_python.png" />
      </Step>
    </Steps>
  </Tab>
</Tabs>

## I2C

I2C (Inter-Integrated Circuit) is a bidirectional 2-wire bus for inter-IC control. Every device on the bus has a unique address. The I2C core supports multi-controller mode, 10-bit target addressing, and 10-bit extendable addressing.

Pins 8 and 10 are configured for I2C by default (GPIO lines 32 and 33, mapping to `i2c4 = qup0_se4 (0x990000)`).

Follow the [Modify serial engine node](./peripheral_interface_overview#modify-serial-engine-node) procedure to enable the I2C interface. After enabling, verify the device nodes:

```bash theme={null}
ls /dev/i2c*
# Expected: /dev/i2c-18  /dev/i2c-19  /dev/i2c-20  /dev/i2c-21  /dev/i2c-22  /dev/i2c-23  /dev/i2c-24  /dev/i2c-25
```

<Tabs>
  <Tab title="Shell">
    <Steps>
      <Step title="Install i2c-tools">
        ```bash theme={null}
        sudo apt install -y i2c-tools
        ```
      </Step>

      <Step title="List I2C adapters">
        ```bash theme={null}
        i2cdetect -l
        ```
      </Step>

      <Step title="Map adapters to device tree nodes">
        ```bash theme={null}
        ls -l /sys/class/i2c-adapter/i2c-*
        ```
      </Step>

      <Step title="Scan for devices on bus 20">
        ```bash theme={null}
        i2cdetect -a -y -r 20
        ```
      </Step>

      <Step title="Read/write device registers">
        ```bash theme={null}
        # Read all registers of device at address 0x38
        i2cdump -f -y 1 0x38

        # Write 0xaa to register 0x01
        i2cset -f -y 1 0x38 0x01 0xaa

        # Read register 0x01
        i2cget -f -y 1 0x38 0x01
        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="C">
    The following example writes `0xaa` to address `0x01` of a device at I2C address `0x38`.

    ```c theme={null}
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <linux/i2c-dev.h>
    #include <sys/ioctl.h>

    #define I2C_DEVICE_PATH "/dev/i2c-1"

    int main() {
        uint8_t data[2] = {0x01, 0xaa};
        int i2c_file;

        if ((i2c_file = open(I2C_DEVICE_PATH, O_RDWR)) < 0) {
            perror("Failed to open I2C device");
            return -1;
        }

        ioctl(i2c_file, I2C_TENBIT, 0);
        ioctl(i2c_file, I2C_RETRIES, 5);

        printf("i2cdetect addr: ");
        for (int x = 0; x < 0x7f; x++) {
            if (ioctl(i2c_file, I2C_SLAVE, x) < 0) {
                perror("Failed to set I2C slave address");
                close(i2c_file);
                return -1;
            }
            if (write(i2c_file, data, 2) == 2)
                printf("0x%x,", x);
        }

        close(i2c_file);
        printf("\r\n");
        return 0;
    }
    ```

    <Steps>
      <Step title="Compile">
        ```bash theme={null}
        gcc i2c.c -o i2c
        ```
      </Step>

      <Step title="Connect sensor to pins 11 and 13, then run">
        ```bash theme={null}
        ./i2c
        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="Python">
    Install `python3-smbus`:

    ```bash theme={null}
    sudo apt install python3-smbus
    ```

    The following example writes `0xaa` to address `0x01` of a device at I2C address `0x38`.

    ```python theme={null}
    import smbus

    def main():
        data = [0x01, 0xaa]
        i2c_bus = None
        try:
            i2c_bus = smbus.SMBus(1)
            print("i2cdetect addr: ", end="")
            for address in range(0x7F):
                try:
                    i2c_bus.write_i2c_block_data(address, 0, data)
                    print("0x{:02X},".format(address), end="")
                except OSError:
                    pass
            print()
        except Exception as e:
            print(f"An error occurred: {e}")
        finally:
            if i2c_bus:
                i2c_bus.close()

    if __name__ == "__main__":
        main()
    ```

    Connect sensor to pins 11 and 13, then run:

    ```bash theme={null}
    python3 i2c.py
    ```
  </Tab>
</Tabs>

## SPI

SPI (Serial Peripheral Interface) is a synchronous full-duplex 4-wire serial bus.

Pins 11 and 13 are configured for SPI by default (GPIO lines 44 and 45, mapping to `spi10 = qup1_se3 (0xa8c000)`).

Follow the [Modify serial engine node](./peripheral_interface_overview#modify-serial-engine-node) procedure to enable the SPI interface.

<Tabs>
  <Tab title="C">
    The following example sends and receives data over SPI with loopback.

    ```c theme={null}
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <linux/spi/spidev.h>
    #include <sys/ioctl.h>

    #define SPI_DEVICE_PATH "/dev/spidev12.0"

    int main() {
        int spi_file;
        uint8_t tx_buffer[50] = "hello world!";
        uint8_t rx_buffer[50];

        if ((spi_file = open(SPI_DEVICE_PATH, O_RDWR)) < 0) {
            perror("Failed to open SPI device");
            return -1;
        }

        uint8_t mode = SPI_MODE_0, bits = 8;
        ioctl(spi_file, SPI_IOC_WR_MODE, &mode);
        ioctl(spi_file, SPI_IOC_WR_BITS_PER_WORD, &bits);

        struct spi_ioc_transfer transfer = {
            .tx_buf = (unsigned long)tx_buffer,
            .rx_buf = (unsigned long)rx_buffer,
            .len = sizeof(tx_buffer),
            .speed_hz = 1000000,
            .bits_per_word = 8,
        };

        if (ioctl(spi_file, SPI_IOC_MESSAGE(1), &transfer) < 0) {
            perror("Failed to perform SPI transfer");
            close(spi_file);
            return -1;
        }

        printf("tx_buffer:\n %s\n", tx_buffer);
        printf("rx_buffer:\n %s\n", rx_buffer);
        close(spi_file);
        return 0;
    }
    ```

    <Steps>
      <Step title="Compile">
        ```bash theme={null}
        gcc spi.c -o spi
        ```
      </Step>

      <Step title="Short pin 11 and pin 13 with a Dupont wire (loopback), then run">
        ```bash theme={null}
        ./spi
        ```
      </Step>
    </Steps>
  </Tab>

  <Tab title="Python">
    Install `python3-spidev`:

    ```bash theme={null}
    sudo apt install python3-spidev
    ```

    ```python theme={null}
    import spidev

    def main():
        tx_buffer = [ord(c) for c in "hello world!"]
        try:
            spi = spidev.SpiDev()
            spi.open(12, 0)
            spi.max_speed_hz = 1000000
            rx_buffer = spi.xfer2(tx_buffer[:])
            print("tx_buffer:\n", ''.join(map(chr, tx_buffer)))
            print("rx_buffer:\n", ''.join(map(chr, rx_buffer)))
        except Exception as e:
            print(f"An error occurred: {e}")
        finally:
            spi.close()

    if __name__ == "__main__":
        main()
    ```

    <Steps>
      <Step title="Short pin 11 and pin 13 with a Dupont wire (loopback), then run">
        ```bash theme={null}
        python3 spi.py
        ```
      </Step>
    </Steps>
  </Tab>
</Tabs>
