OrangePi i96 Notes

Pat Beirne

2021-08-29

Overview

Author: Pat Beirne patb@pbeirne.com
Date: 2021-07-14

[TOC]

The OrangePi-i96 is one of the least expensive SBC’s capable of running Linux. It is a member of the Linaro i96 family, and has a 40 pin connector that has been standardized by Linaro.

However, the currently shipping version of the OPi-i96 does not power up properly. This application note describes a few changes that can help get the OPi-i96 into a working and usable state.

  1. make the operating system bootable
  2. fix the GPIO control settings
  3. fix the I2C data speed
  4. other general comments

Note: This document is written to not use the WiringPi utility, because I could not get it working on the OrangePi-i96. I wrote my own, called opio

Note: Almost all of these notes also apply to the OrangePi 2G-IOT board.

1. Operating System

The OrangePi website has downloadable images for Ubuntu and Debian versions of the operating system. The installation instructions on the OrangePi webite will instruct you on how to create a microSD card with the operating system, and how to boot the first time.

Both of these builds expect that there is a sound system (microphone and speakers). But the OPi-i96 board is a cut-down version of the OPi-2G-IoT board, with the microphone and speaker removed.

When the OS boots the first time, it goes into installation mode and works fine. But when the system boots a 2nd time, it tries engage the ALSA sound system (which isn’t there!) and locks up.

To solve this problem, make sure that during the 1st boot up, you remove the ALSA sound system:

    cd /usr/sbin
    sudo mv alsactl alsactl.bak   # execute this on the target OrangePi-i96

If, for some reason, you missed that opportunity, try this: remove the microSD card from the OrangePi, mount it on a Linux computer and:

    rm <mount-point>/usr/sbin/alsactl          # execute this on a Linux desktop, with the sdcard mounted

After a sync and umount, you can replace the microSD card in the OPi-i96 and reboot. It should proceed through the boot process and be available to log into. [Strangely, after the 2nd boot, you can rename the alsactrl program back to its original name and the system boots!]

2. GPIO

The currently shipping u-boot+kernel boots up with the microcontroller (RDA8810) in a strange state, with some GPIO pins set to operate in special-function mode, and some set into GPIO mode, and the mix doesn’t seem to match the intended functions described in the i96 spec.

This table describes the state of the 40 pin bus. Column ‘mode’ is the mode setting of the pin after boot; some of these agree with the i96 spec, some do not. The ‘(rda)’ column is the pin name according to the RDA data sheet. The ‘kernel’ column is the GPIO numbering system used by the Linux kernel. And the ‘verified’ column indicates that I verified(measured) the function of the pin in gpio mode. The ‘alt’ column indicates the special function available on this pin, using the Linux naming scheme.

If there are ‘special function’ groups that you don’t need for your project, you may use these pins as GPIO pins. For example, if you’re not using sound on the PCM group, you can recover pins 15, 17, 19 & 21 for use as general purpose pins.

verified gpio(kernel) gpio(rda) alt mode° i96 name pin pin i96 name mode° alt gpio (rda) gpio (kernel) verified
GND 1 2 GND
yes gpio40 gpio_b8 ttyS0 gpio UART0_CTS 3 4 PWR_BTN_N note 2
yes gpio104 gpio_c8 ttyS0 ttyS0 UART0_TX 5 6 v_rtc 1.4V
yes gpio103 gpio_c7 ttyS0 ttyS0 UART0_RX 7 8 SPI0_CLK gpio spi2 gpio_a2 gpio2 yes
yes gpio41 gpio_b9 ttyS0 gpio UART0_RTS 9 10 SPI0_DI gpio spi2 gpio_a4 gpio4 yes
yes gpio14 gpio_a14 ttyS1 ttyS1 UART1_TX 11 12 SPI0_CS gpio spi2 gpio_a6 gpio6 yes
yes gpio102 gpio_c6 ttyS1 ttyS1 UART1_RX 13 14 SPI0_DO gpio spi2 gpio_a3 gpio3 yes
yes gpio0 gpio_a0 i2c-1 i2c-1 I2C0_SCL 15 16 PCM_FS pcm pcm gpio_a10 gpio10 yes
yes gpio1 gpio_a1 i2c-1 i2c-1 I2C0_SDA 17 18 PCM_CLK pcm pcm gpio_a9 gpio9 yes
yes gpio38 gpio_b6 i2c-2 i2c-2 I2C1_SCL 19 20 PCM_D0 pcm pcm gpio_a13 gpio13 yes
yes gpio39 gpio_b7 i2c-2 i2c-2 I2C1_SDA 21 22 PCM_DI pcm pcm gpio_a11 gpio11 yes
yes gpio15 gpio_a15 ttyS1 ttyS1 GPIO_A 23 24 GPIO_B lcd lcd gpio_a20 gpio20 yes
yes gpio56 gpio_b24 gpio GPIO_C 25 26 GPIO_D ttyS2 ttyS2 gpio_d2 gpio66 yes
yes gpio67 gpio_d3 ttyS2 ttyS2 GPIO_E 27 28 GPIO_F lcd lcd gpio_a22 gpio22 yes
yes gpio30 gpio_a30 lcd lcd GPIO_G 29 30 GPIO_H lcd lcd gpio_a29 gpio29 yes
yes gpio28 gpio_a28 lcd lcd GPIO_I 31 32 GPIO_J lcd lcd gpio_a27 gpio27 yes
yes gpio26 gpio_a26 lcd lcd GPIO_K 33 34 GPIO_L lcd lcd gpio_a25 gpio25 yes
2.9V v_pad +1v8 35 36 SYS_DCIN n/c
5V(usb) +5v 37 38 SYS_DCIN n/c
GND 39 40 GND

° NOTE: these are the default modes with this software:

function version
u-boot U-Boot 2012.04.442-rel5.0.2-g5ee06c1-dirty (Mar 18 2020 - 18:51:54)
kernel Linux version 3.10.62-rel5.0.2+ (Linaro)
distribution Ubuntu 16.04

NOTE 2: this pin measures 0v normally, rises to 3.8V when the power button is pushed; this appears to be the opposite of the i96 spec. The schematic indicates that it’s used as an interrupt, so this inversion probably doesn’t matter.

In order to align the bus pins with the intended function of the i96 bus, we need to make some changes. The UART1, I2C and I2S/PCM pins are configured correctly. Pins 3, 9 (uart), 8, 10,12 and 14 (spi) need to be set to ‘special-function’. And all the pins between 23 and 34 need to be set to ‘gpio’ mode. At the bottom of this file you can find a Python3 utility to restore the pins of the microproccesor to the states intended by the i96 bus.

The existing linux kernel does not give access to the pin-function control registers, but there are a couple of ways to access those registers from the linux environment:

This document was written using devmem2 to locate and test the control registers.

Here are the relevant registers:

Register Name Register Address Usage Existing State Desired State
IOMUX 0x11a0.9008 special-function/gpio select for group C 0x7fe0.003f 0x7fe0.003f
IOMUX-A 0x11a0.900c ibid, group A 0x0002.10fc 0x7e52.90a0
IOMUX-B 0x11a0.9010 ibid, group B 0x3f00.033f 0x3f00.003f
IOMUX-D 0x11a0.9014 ibid, group D 0x0000.0010 0x0000.001c
GPIO-DIR 0x11a0.8000 direction register for group C
GPIO-DATA 0x11a0.800c data register for group C
GPIO-A-DIR 0x2093.0000 direction register for group A
GPIO-A-DATA 0x2093.000c data register for group A
GPIO-B-DIR 0x2093.1000 direction register for group B
GPIO-B-DATA 0x2093.100c data register for group B
GPIO-D-DIR 0x2093.2000 direction register for group D
GPIO-D-DATA 0x2093.200c data register for group D

The patterns shown on the first 4 lines of this table will set the GPIO pins to align with the i96 bus specifications. And give you access to 12 general purpose GPIO pins (23-34). Note: a ‘1’ written into this register will select a pin for GPIO; a ‘0’ selects the special-function mode.

The last 8 entries are for information only. The Linux GPIO device driver /sys/class/gpio works perfectly; there’s no need to bypass it. (The linux /dev/gpiochip does not exist in this kernel, since it’s 3.10)

For example, after the GPIO correction, to toggle pin 26 (i96-name: GPIO-D, linux-name: gpio66), simply:

cd /sys/class/gpio  
echo 66 > export
cd gpio66
echo out > direction
echo 1 > value
echo 0 > value

## alternatively, use gpio or opio
opio mode 66 out    
# this will also do the 'export' function and create /sys/class/gpio/gpio66
opio write 66 1
opio write 66 0

The code to restore the GPIO pins to the i96 standard is in the file gpio_fixup.py. I recommend you install it at /usr/local/bin/gpio_fixup.py and add it to /etc/rc.local near the end of the boot sequence.

GPIO State at Boot Time

Be aware that if you connect ‘output’ hardware to the 40pin connector, the GPIO’s may not be set properly in the 5-20 seconds between U-Boot and running the gpio-correction code. This time can stretch even longer if the Wifi module takes time to stabilize.

If you want to be sure about the state of an output, use one of these:

Prior to setting the gpio pin as an output, these pin will be hi-impedance. Design your hardware that it operates properly in the absence of a drive-voltage.

Once the system has booted, you can set the GPIO mode on pins 3 and 9 using the opio program: opio mode 40 out and opio mode 41 out.

Of course, all of the above comments apply to the current uboot. A modified version could set the other i96 pins properly, but modifying uboot is beyond my skill level.

2G-IOT board

The 2G-IOT board is very similar, except that the GPIO bits are mostly set correctly. Here is the state of the pins at power-on (using the currently shipping uboot/kernel)

opio -2 status

+-----+-----+----------+------+-+ OrgPi 2G-iot +-+------+----------+-----+-----+
| gpio| alt | i96 Name | Mode | V | Physical | V | Mode | i96 Name | alt | gpio|
+-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
|     | 2.8v| V_PAD    |      |   |  1 || 2  |   |      | VDD_IN   | 5V  |     |
| 63  | SDA | I2C1.SDA | alt  | ? |  3 || 4  |   |      | VDD_IN   | 5V  |     |
| 62  | SCL | I2C1.SCL | alt  | ? |  5 || 6  |   |      | GND      |     |     |
| 56  |     | GPIO.B24 | out  | 0 |  7 || 8  | ? | alt  | UART2.TX |     | 104 |
|     |     | GND      |      |   |  9 || 10 | ? | alt  | UART2.RX |     | 103 |
| 102 | RX  | UART1.RX | alt  | ? | 11 || 12 | 1 | out* | GPIO.B5  |     | 37  |
| 14  | TX  | UART1.TX | alt  | ? | 13 || 14 |   |      | GND      |     |     |
| 15  | CTS | UART1.CT | alt  | ? | 15 || 16 | 0 | in*  | GPIO.C5  |     | 101 |
|     | 2.8v| V_PAD    |      |   | 17 || 18 | 0 | in*  | GPIO.C25 | SIM | 121 |
| 4   | DI  | SPI2.DI  | in*  | 0 | 19 || 20 |   |      | GND      |     |     |
| 3   | DIO | SPI2.DIO | in*  | 0 | 21 || 22 | ? | alt  | UART1.RT | RTS | 16  |
| 2   | CLK | SPI2.CLK | in*  | 0 | 23 || 24 | 1 | in*  | SPI2.CS0 | CS0 | 5   |
|     |     | GND      |      |   | 25 || 26 | 0 | in*  | SPI2.CS1 | CS1 | 6   |
| 1   |     | I2C2.SDA | alt  | ? | 27 || 28 | ? | alt  | I2C2.SCL | SCL | 0   |
| 122 | SIM | GPIO.C26 | in*  | 0 | 29 || 30 |   |      | GND      |     |     |
| 123 | SIM | GPIO.C27 | in*  | 1 | 31 || 32 | 0 | out* | UART2.RT | RTS | 41  |
| 124 | LCD | GPIO.C28 | in*  | 0 | 33 || 34 |   |      | GND      |     |     |
| 125 | LCD | GPIO.C29 | in*  | 0 | 35 || 36 | 0 | out* | UART2.CT | CTS | 40  |
| 126 | LCD | GPIO.C30 | in*  | 0 | 37 || 38 | ? | alt  | I2C3.SCL | SCL | 38  |
|     |     | GND      |      |   | 39 || 40 | ? | alt  | I2C3.SDA | SDA | 39  |
+-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
Note: *these pins are set to GPIO mode but do NOT have exports in /sys/class/gpioNote: *these pins are set to GPIO mode but do NOT have exports in /sys/class/gpio

If you wish to use SPI2, you will have to set the mode pins to ‘alt’; if not, you have 5 extra gpio pins already set up as inputs. Gpio pins 40 and 41 are set to outputs. I2C1, UART1, I2C2 and UART2 (tx+rx) are already set up and ready to use.

GPIO/OPIO program

You can control the state of the pins using the opio command line tool, documented here in this file, or here if you want to download it.

3. I2C Speed

optional

The data rates on the two I2C busses seems to be a bit off. Using the current shipping build, the i2c-1 bus runs at 266kb/s, and the i2c-2 bus runs at 160k

b/s. Neither of these are frequencies called out in the I2C standard, although they will work properly with ‘400kB/s’ I2C devices.

There may be cases where you want better control over the bus speeds, and the current Linux I2C driver does not implement hooks to allow a speed change. Use the devmem2 progam to write these words.

Bus (linux name) Pins (40 pin connector) Register Write
i2c-1 15 (scl), 17 (sda) 0x2096.0000 0xnnn.0000 then 0xnnn.0001
i2c-2 19 (scl), 21 (sda) 0x2097.0000 0xnnn.0000 then 0xnnn.0001

where ‘nnn’ = one of these:

The i2cdetect program does not seem to work well on this microprocessor. If you write your own i2c scanner, it will work ok. Try this:

#!/usr/bin/env python3

import smbus
bus = smbus.SMBus(1) # 1 indicates /dev/i2c-1

for device in range(128):
      try:
         bus.read_byte(device)
         print(hex(device))
      except: # exception if read_byte fails
         pass

The 2G-IOT board operates the same way.

4. Useful Info

LEDs

There are 3 green LED’s located near between the camera connector and the USB-A connector. You can control them with GPIO pins, 1=lit.

Method:

  cd /sys/class/gpio
  echo 125 > export
  cd gpio125
  echo out > direction
  echo 1/0 > value

  # or
  opio write 125 1
  opio write 125 0

NOTE With the current uboot/kernel combination, the LEDS start off in an indentermined state, which is not reflected properly with the opio leds command. Once you start using the LED’s though, they operate properly.

ADC

There is an embedded ADC converter on the SOC chip (RDA8810), but we have no access to it directly.

If you wish, you can solder a wire from the 3-pin battery connector/pads (J302) over to a spare pin on the 40 pin i96 connector, and you can measure a voltage using channel 1 of the ADC (ac1 at 0x11a0.9054). Again, the software for ADC doesn’t seem to be included in the existing Linux kernel.

To measure the voltage without a kernel driver, you can use these registers:

  devmem2 0x11a09054 w 0x80000000    # write to bit 31
                       # triggers   an ADC conversion....wait 50us
  devmem2 0x11a09054                 # read the lower 10 bits; bit 10 = DATA_VALID

Battery

It appears that you can connect a 1-cell LiPo battery to J302; this seems to bhe the 3 oval pads beside the micro-USB connector. I did not test this.

USB

It appears there is only one USB bus, shared by the typeA and micro connectors

UARTS

The microprocessor has 3 uarts. The datasheet numbers these uart1 (ttyS1), uart2 (ttyS2) and uart3 (ttyS0). The first two are available on the i96 connector, and the ttyS0 is the ‘debug’ serial connector, whose pins do not appear on the i96 connector. See below

If you don’t need the CTS and RTS functions of uart1 (ttyS1), then you can leave these pins in GPIO state and access them through gpio40 and gpio41 respectively. See below

The debug serial port powers up at 921600 baud. If you would prefer the standard 115200, edit /media/boot/boot.cmd where the baud rate is set, then execute this: [verified]

mkimage -C none -A arm -T script -d /media/boot/boot.cmd /media/boot/boot.scr

Modem

Even though the ‘modem’ section of the microprocessor is not used, you must allow the modem driver to be installed. The modem chip includes the Wifi & Bluetooth functions. The microprocessor (RDA8810) will not function without the modem co-processor functioning.

Console Text Color

Immediately after a standard boot, the Ubuntu and Debian distribution will notify you with a red Welcome to orangepi banner. Following that, the screen text is usually a feint grey color. You can reset it to hard black with

   tput sgr0

Alternatively, you can edit the offending banner file at /etc/update-motd.d/100-fs-warning and change the last escape code from \033[37m into \033[0m. [verified]

Wifi

Lockup

There are cases where the connection between the RDA and the Wifi chip gets locked up, and the system will loop with messages like:

[170837.809875] [RDAWLAN_ERR]:<wland_sdio_send_pkt,480>: wland_sdio_flow_ctrl failed!
[170837.810791] [RDAWLAN_ERR]:<wland_proto_cdc_data,232>: set_dcmd failed status: -5
[170837.811706] [RDAWLAN_ERR]:<wland_run_escan,773>: SCAN error (-12)

One possible solution is to remove-&-reinstall the driver module. As root:

rmmod rdawfmac
modprobe rdawfmac
Unstable MAC Address

The default install of Ubuntu and Debian will generate a new MAC address for the Wifi device every time the system powers up. If you are running inside a home network, the DHCP server will probably assign a new IPv4 address after ever power-reboot, which can make it tricky to locate the device on your network.

[As the kernel boots, the wireless driver queries the modem for the MAC address. This processor is intended to be used in a smartphone, with a permanent battery on the modem, so it can remember its MAC address between reboots. Since we have no battery, the modem returns “invalid” and the wireless device starts up with a random IP address.]

Various of finding your i96 device on your LAN:


Alternatively, I have re-built the Linux kernel module for the wifi so that it uses a fixed MAC address. Download it and store it on your OrangePi-i96 at /lib/modules/3.10.62-rel5.0.2+/kernel/drivers/net/wireless/rdaw80211/rdawlan/

At module-init time, it uses the first 6 bytes of the file at /data/misc/wifi/WLANMAC as the MAC address. Make sure to put something unique into that file so that you don’t have multiple i96 boards with the same MAC address. I suggest that the first 2 bytes be 00:00, that seems to work best.

If you decide to build this kernel module yourself, the relevent flag is WLAND_MACADDR_DYNAMIC (defined) and USE_MAC_FROM_RDA_NVRAM (undefined)

Wifi AP

Some people have asked about running hostapd and changing the i96 board into an Access Point (AP). Even though the device driver seems to be written to allow it, and the driver reports AP in its capability list, I don’t think anyone has succeeded in creating an Access Point.

More GPIO

If there are sections of the i96 bus special functions that you don’t need, you can recover these pins for use as GPIO pins.

For example, I do not use the i2s feature of the board, so pins 16,18,20 & 22 (i96 connector) can be converted to GPIO

Pins 16,18,20 and 22 correspond to RDA gpio_a10, gpio_a9, gpio_a13 and gpio_a11. To change these pins into GPIO, we need to write a ‘1’ into the IOMUX register for group A. The bit mask is 0b0010.1110.0000.0000 = 0x2e00, and the IOMUX register for group A is 0x11a0.900c.

  devmem2 0x11a0900c
  Value at address 0x11a0900c: 0x7e5290a0
  # read the result and use a bit-wise OR with 0x2e00 to set the bits
  devmem2 0x11a0900c w 7e52bea0

After this operation, you can access the four pins using the linux gpio mechanism at /sys/class/gpio and address gpio10, gpio9, gpio13 and gpio11 respectively

Function Group RDA Pins LInux GPIO Change to GPIO Change to Special Function
uart2 c7,c8 103,104 *0x11a0.9008 |= 0x0000.0180 *0x0x11a0.9008 &= 0xFFFF.FE7F
– also uart2 b8, b9 40,41 *0x11a0.9010 |= 0x0000.0300 *0x0x11a0.9010 &= 0xFFFF.FCFF
uart1 c6 102 *0x11a0.9008 |= 0x0000.0040 *0x0x11a0.9008 &= 0xFFFF.FFBF
– also uart1 a14 14 *0x11a0.900c |= 0x0000.4000 *0x0x11a0.900c &= 0xFFFF.BFFF
i2c2 a0, a1 0,1 *0x11a0.900c |= 0x0000.0003 *0x0x11a0.900c &= 0xFFFF.FFFC
i2c3 b6, b7 38,39 *0x11a0.9010 |= 0x0000.00C0 *0x0x11a0.9010 &= 0xFFFF.FF3F
spi2 a2, a3, a4, a6 2,3,4,6 *0x11a0.900c |= 0x0000.005C *0x0x11a0.900c &= 0xFFFF.FFA3
i2s/pcm a9, a10, a11, a13 9,10,11,13 *0x11a0.900c |= 0x0000.2E00 *0x0x11a0.900c &= 0xFFFF.D1FF

This chip RDA8810 does not have PWM on the GPIO pins. The fastest you can change them as outputs is at OS speeds. I wouldn’t count on anything faster than 2sec, since the Linux OS may be doing other things when you require a GPIO pin to change.

Appendix: Known usage of GPIO pins

c2 = [IN] hi “boot from TF card”, low “boot from nand”
c5 = [OUT] high lights LED5
c29 = hi to light LED3
c30 = hi to light LED2

a7 = [IN] headset detect (n/a)
a17 = [IN] otg_power_enable
a5/b0/c1/c2/c3/c4 = [IN] internal solder pads to select RDA chip version
a8 = 32kHz clock out (internal connection)
a12 = i2s_d1 (not connected)
a18/19/21/23/31 = not connected
b1 = bt_sleep, connect to modem
b2 = wf_intn, connect to modem
b4 = [IN] tf_detect, low when sd card is present
b5 = connected to the plug_in pin, set to 0v in sd_card boot mode (switch U3-7)
b10-23 = connected to the camera interface
b25-29 = n/c
b30-31 = i2c bus to talk to camera & modem
c9-20 = sdcard (internal connection)
c21/22/23/24 = spi1 (not connected)
c25-28 = n/c
d4 = n/c

Linux driver numbering

Special function mode:

RDA device name i96 Bus Name Linux device name
uart1 UART0 /dev/ttyS1
uart2 UART1 /dev/ttyS2
uart3 n/a /dev/ttyS0 (debug terminal; not on i96 bus)
i2c1 n/a /sys/class/i2c/i2c-0 (link to modem chip; not on i96 bus)
i2c2 I2C0 /sys/class/i2c/i2c-1
i2c3 I2C1 /sys/class/i2c/i2c-2
spi2 SPI0 /sys/class/spi_master TODO: verify
i2s2 PCM /sys/class/pcm/pcm-1 TODO: verify

GPIO mode:

RDA gpio driver group IOMUX address Linux gpio device numbers
Group C 0x11a0.9008 gpio96-gpio127
Group A 0x11a0.900c gpio0-gpio31
Group B 0x11a0.9010 gpio32-gpio63
Group D 0x11a0.9014 gpio64-gpio68 (there are only 5 pins)

Write a ‘1’ into the IOMUX register to set a bit to GPIO mode. Write a ‘0’ to set the same bit to ‘special function’ See this

The actual gpio value registers are at 0x2093.0000(group a), 0x2093.1000(group b), 0x2093.2000(group d) and 0x11a08000(group c) address + 0 = “data direction register 0=output”
+ 4 set for “dir = out”
+ 8 set for “dir = in”
+ c for “read/write”
+ 10 set for “write 1”
+ 14 set for “write 0”
+ 18 gpio interrupt control reg

Resources on the net:

file iomap-rda8810.h

reg_cfg_regs_rda8810.h

Other sources for OrangePi information

Things to do on a fresh install

NOTE there are some wifi hotspots that refuse to DHCP/DHCLIENT but others are fine…..why?

NOTE if you go to compile the source for uboot & kernel, you’ll need to load the 32bit versions of the libstdc++6 libraries

OrangePi 2G-IOT

The 2G-IOT version of this board includes a GSM tranceiver and an audio subsystem. Otherwise it is very similar to the i96 board and most of the above notes apply.

NOTE: The i2c-0 device is connected to pins 3/5 (I2C1_SDA/I2C1_SCL) on the 2Giot pin connector. It is NOT recommended to use this bus, because it is also connected to the modem chip, and is used for chip-to-chip communication. For the same reason, do not use opio to modify the operation of these pins.

OPIO

The RaspberryPi and OrangePi environment uses an app simply called gpio to control the GPIO pins. The original verion was written by Gordon Henderson as part of his WiringPi project and has been ported to work on most of the OrangePi series boards. But there is no (commonly available) version for the OrangePi-i96. Rather than port it, I decided to rewrite it in Python3. To be safe, it has a new name: opio. It operates very similarly to the original gpio program, with fewer features.

With opio you can:

opio is written in Python3, which is available on the stock Linux distribution for both the i96 and 2G-IOT boards. This of course makes it a bit slow, taking about 500ms to do anything.

The term mode is whether a pin is a GPIO or being used as its alternate function, and whether it’s an input or output. The term value means 1/0, an on these pins, that means 2.8V or 0V.

Usage
  opio [-d] mode <n> [in | out | alt]
  opio [-d] read <n>
  opio [-d] write <n> <value>
  opio [-2] [readall | readallx | exports | leds]

For the first 3 forms of the command, the number is the linux-gpio number, ranging from 0 to 127. [0..31 is portA, 32..63 is portB, 64……67 is portD and 96..127 is portC]

The first version sets the mode for a pin. If the mode is ‘in’ or ‘out’, the pin is set to GPIO mode and the ‘export’ is created. If the mode is set to ‘alt’, the pin is set to its alt-function mode (like i2c or uart) and the ‘export’ is deleted. You can use the -d option to prevent the export from being created or deleted.

The second version simply reads value of the pin and returns ‘1’ or ‘0’. If the pin is an ‘out’ pin, the last value written will be returned.

The third version writes a ‘1’ or a ‘0’ to the pin. If the pin is in mode ‘in’ or ‘alt’, this command will have no effect.

As a convenience, the read and write commands will automatically set the mode on the GPIO pin and create an export. So, generally, the mode command is only required if you wish to change a pin back to its `alt’ function.

The ‘readall’ returns a chart very similar to the chart created by gpio readall original gpio program. This includes the gpio number, the i96 bus name, the pins alternate function, the current mode and value.

The ‘readallx’ returns a chart with extra information, such as the RDA pin assignments. The ‘exports’ command lists which pins have existing exports in the /sys/class/gpio folder. and the ‘leds’ command lists the state of the LED’s on board. [Note: the LEDs start up in an odd state and the ‘leds’ command will not relect the correct state until the LEDs have been manipulated]