7 7
Larry Bank

ArmbianIO API proposal

Recommended Posts

@TonyMac32,
if the table has not been built so nicely like the one from Asus tinker board..

Linux Userspace Naming Convention  is this the way to go ?     Which looks a bit difficult, doable but error-prone.

 

If the above is the way to go, why did you guide me to the DTS - is this an easier way I just don't understand?

Share this post


Link to post
Share on other sites

@Tido

Not sure if this is helpful but a quick look at the Tinkerboard GPIO number reveals a potential pattern.

eg.

GP8A4 = 252.

The letter A could represent 'subract' therefore:

(8 x 32) -4 = 252.

 

GP5B4 = 164.

The letter B could rebresent ' add' therefore:

(5 x 32) + 4 = 164.

 

GP5C3 = 171.

The letter C could represent '+ 8' therefore:

(5 x 32) + 8 + 3 = 171

 

GP7C2 = 234.

(7 x 32) + 8 + 2 = 234.

 

However, I'm not sure how GP0C1 = 17

Share this post


Link to post
Share on other sites

Hi @Tido,

 

   I was just pointing in the general direction of all the info I had.  I haven't done anything with Le Potato as far as GPIO is concerned.  The info you linked is specific (at least partly) to i.MX6, so you may be treading some deep water trying to read that across to a different SoC.

Share this post


Link to post
Share on other sites

Hopefully no one will object, but I just added support for the Raspberry Pi Zero to the ArmbianIO supported boards. It's easy to detect with uname (the only ARMv6 board). If I find a reliable way to detect the other RPI boards, I'll add support as well. Makes it easier for me to test code. I also wrote a SSD1306 OLED library (I2c and SPI support) using ArmbianIO. I'll share it on my github account hopefully later today.

Share this post


Link to post
Share on other sites
5 hours ago, Larry Bank said:

Hopefully no one will object, but I just added support for the Raspberry Pi Zero to the ArmbianIO supported boards. It's easy to detect with uname (the only ARMv6 board). If I find a reliable way to detect the other RPI boards, I'll add support as well

IMHO, why adding a GPIO library called ArmbianIO, when Armbian does not support RPis? To my knowledge, the only RPis with 'Armbian userland' are @tkaisers OMV builds. :P 

 

but from another project, I had a look at it proc/cpu info might help?

 

    """Detect the version of the Raspberry Pi.  Returns either 1, 2 or
    None depending on if it's a Raspberry Pi 1 (model A, B, A+, B+),
    Raspberry Pi 2 (model B+), or not a Raspberry Pi.
    """
    # Check /proc/cpuinfo for the Hardware field value.
    # 2708 is pi 1
    # 2709 is pi 2
    # 2835 is pi 3 on 4.9.x kernel
    # Anything else is not a pi.

 

Share this post


Link to post
Share on other sites
6 hours ago, Larry Bank said:

If I find a reliable way to detect the other RPI boards, I'll add support as well.

 

Please check /proc/device-tree/model (applies also to all boards Armbian supports and there should be even a way to use a somewhat similar method at least with Allwinner legacy kernel since I tried some time ago to make fex contents compatible with the DT 'model name' mainline kernel uses for the same devices)

Share this post


Link to post
Share on other sites
1 hour ago, chwe said:

IMHO, why adding a GPIO library called ArmbianIO, when Armbian does not support RPis? To my knowledge, the only RPis with 'Armbian userland' are @tkaisers OMV builds. :P 

 

I wrote it specifically for Armbian, but it doesn't hurt to support RPI boards. This way I can test my code across a wider range of boards. I have a desk full of ARM SBCs from various vendors (including RPF). I tend to write code to support the hardware I own.

Share this post


Link to post
Share on other sites

It has already been mentioned before, gpiochip becoming character devices but as I collect more information about it, I came across this introduction to the topic and some explanation .. links to the sources are in the article as well

https://www.cnx-software.com/2017/11/03/learn-more-about-linuxs-new-gpio-user-space-subsystem-libgpiod/

 

By the way, the talk of Bartosz (I am 11min in now) is a good lead into this topic - he just makes quite often ähhhh

Share this post


Link to post
Share on other sites

I've created Python bindings with Swig using a script that should install all dependencies and create an armbianio module and install locally with pip, so it's globally accessible in Python. I created a PR for Larry, but you can grab it at https://github.com/sgjava/ArmbianIO until the merge happens. I included a simple LED blink program that uses pin 12 (ArmbianIO mapping) for the NanoPi Duo. It would be nice to test other SBCs as well.

Share this post


Link to post
Share on other sites

I merged in Steven's python changes and changed the init function to allow specifying the board name. This allows it to work on older Armbian and non-Armbian Linux builds. I'll update my Nokia LCD library to reflect this change.

Share this post


Link to post
Share on other sites

I'm working with Larry to get the callback working. Swig doesn't generate C function pointer based callback wapper correctly, so you have to hand code it. It involves some yucky coding https://www.safaribooksonline.com/library/view/python-cookbook/0596001673/ch16s07.html, but if I get the pin number back from the callback it can be reduced to a single function instead of wiringPi style one function per pin! https://github.com/WiringPi/WiringPi-Python/blob/master/wiringpi.i

Share this post


Link to post
Share on other sites

OK, I have the Python Swig wrapper and ctypes example using callbacks. Swig wrappers do not work with C to Python callbacks (C function pointer to Python object). In fact, I ignore wrapper generation for AIOAddGPIOCallback in Swig interface file, so there will be no confusion. Maybe I'll try Java wrapper next when I have time. It also makes sense to create a RPi.GPIO wrapper as a drop in replacement for Python libraries that depend on it (like Luma.OLED) with proper BOARD and BCM mappings for each board.

 

One of the nice things is ctypes allows Python code to act like the C code with callbacks. Multiple callbacks can go to one function (I added the pin number, so you can tell where it came from) or do one to one callbacks. This is light years ahead of the wiringPi Python wrapper which uses a gigantic switch statement covering all the pins!

 

Here's the built in button example using a callback https://github.com/bitbank2/ArmbianIO/blob/master/python/button.py

Share this post


Link to post
Share on other sites

I just added support (header pin to GPIO table) for the Banana Pi-M2 Zero board. Even though it's an H2+ SoC, BPI decided to use very different GPIO mappings from Orange Pi. The Armbian build supplied by BPI looks to be a hacked up 5.36 release. Hopefully their changes will get merged into the main Armbian builds soon. The bluetooth chip is not enabled by default and probably requires some magic DTB numbers to get it working. Wifi works fine, but you need to add your own IPX antenna because it doesn't come with one.

Share this post


Link to post
Share on other sites

A new wrinkle to this idea. I've been working with Arduinos lately and thought it would be useful to extend the ArmbianIO concept to use them as "slave" interfaces for sensors/displays/etc. This is an experiment I'm working on and would like some feedback. The idea is that the ArmbianIO API can be used identically on Windows/Mac/Linux. On a remote setup, an Arduino will be used as an I/O slave listening for commands over the serial port. The ArmbianIO you compile on your PC will translate the I2C/SPI/GPIO functions into strings of commands/data over the serial port. Below is a video of my https://github.com/bitbank2/oled_example project running on my Mac and the same exact C code running on my Orange Pi Lite board next to it:

 

 

Please let me know your thoughts.

Share this post


Link to post
Share on other sites

I have the Java wrapper working pretty good. Same issues with Swig as generating the Python wrappers. Pointer (function, char array, etc.) parameters generate worthless code without a lot of manual man handling. Like using ctypes with Python I used JNA for Java, thus no generated code is needed. See https://github.com/bitbank2/ArmbianIO/blob/master/java/Button.java for an example. I need to extract the full interface into it's own file, so there no need to embed it in each program. I'll wrap that up when I port all the Python demos over to Java.

 

I have I2C and SPI examples for Python, so pretty much all the features of ArmbianIO have been tested. The nice thing is the API is the same for all languages, so unlike RPi.GPIO you can pick your language. Once I've built everything out I'll use Valgrind to verify there are no memory leaks high level code to C.

 

You can see where I fixed most of the OpenCV Java memory leaks https://github.com/sgjava/opencvmem

Share this post


Link to post
Share on other sites
3 hours ago, zador.blood.stained said:

AFAIK we are talking about WiringOP forks in general, not only ArmbianIO. And as I remember RPI.GPIO allows using 2 different pin numbering schemes - SoC ("BCM") numbering and pin header ("RPI") numbering. 

ArmbianIO is not a fork of WiringOP. I wrote ArmbianIO because of the terrible situation with WiringOP and WiringNP. Using the BCM numbering on Allwinner boards is understandable for RPI compatibility, but limits what you can do with non-BCM chips. I thought a fresh start which treats all boards as unique and allows more than 40-pins of GPIO header would be wiser than another "crutch" of a hacked up WiringPi copy. I have a wide variety of boards and ArmbianIO (even running on Raspberry Pi boards) allows a consistent way to work with GPIO/I2C/SPI. I know that when I hook an LED or switch to a GPIO pin, I can run the same code on any of my boards and connect it to the same header pin and it will work without modifying my code.

 

chwe: splited from https://forum.armbian.com/topic/6197-hardware-line-is-missing-on-proccpuinfo/  cause I think it's better to keep this in this thread.

 

Share this post


Link to post
Share on other sites
11 minutes ago, Larry Bank said:

added a new option that lets you manually specify the board by name if it doesn't see the machine.id

 

Relying on /var/run/machine.id while working with Armbian might not be a good idea since we considered this feature already 18 months ago somewhat deprecated (when we turned armhwinfo into tuneperformance and stopped all auto detection at boot -- currently it only transfers info from /etc/armbian-release to /var/run/machine.id). So the better idea is to rely alternatively on /proc/device-tree/model or compatible (this will be fed with mainline kernel from the string defined in DT, on Raspberries the mythical firmware does some additional 'magic' and also allows you to differentiate between different board revisions based on autodetection or let's better say reading out the preprogrammed 'Hardware Revision Code')

Share this post


Link to post
Share on other sites
2 minutes ago, tkaiser said:

 

Relying on /var/run/machine.id while working with Armbian might not be a good idea since we considered this feature already 18 months ago somewhat deprecated (when we turned armhwinfo into tuneperformance and stopped all auto detection at boot -- currently it only transfers info from /etc/armbian-release to /var/run/machine.id). So the better idea is to rely alternatively on /proc/device-tree/model or compatible (this will be fed with mainline kernel from the string defined in DT, on Raspberries the mythical firmware does some additional 'magic' and also allows you to differentiate between different board revisions based on autodetection or let's better say reading out the preprogrammed 'Hardware Revision Code')

I'll explore fixing the board name situation using your suggestion. Another reason I shared ArmbianIO as open source was for other people to contribute. @sgjava has already made some significant contributions such as Python and Java wrappers for it.

Share this post


Link to post
Share on other sites
8 minutes ago, Larry Bank said:

I'll explore fixing the board name situation using your suggestion. Another reason I shared ArmbianIO as open source was for other people to contribute.

 

I really hope ArmbianIO spreads widely. And relying alternatively on /proc/device-tree/* might help with user adoption. For example once DietPi users start to use ArmbianIO it could be surprising that ArmbianIO only works on approx half of the boards DietPi 'supports' (since DietPi relies on Debian OS images found somewhere or uses Armbian's build system to create crippled Armbian images with the DietPi menu stuff on top sold then as 'DietPi' to their users -- so if their OS images started as Armbian there will be /var/run/machine.id... otherwise not).

 

BTW: In Armbian for all the Allwinner boards that run legacy kernel we tried to use exactly the same string as /proc/device-tree/model to let this method work regardless of legacy or mainline kernel. Since other projects out there (H3Droid, RetrOrangePi, Lakka) also use our fex files they should become compatible to this 'other fallback' too (at least that was my intention behind these adjustments made a while ago). Some details: https://tech.scargill.net/banana-pi-m2/#comment-27947

 

 

Share this post


Link to post
Share on other sites

It shouldn't be a big deal to write a RPi.GPIO API using ctypes against ArmbianIO (you can see the demo apps I already built using Python and ArmbianIO). Then libraries like Luma.OLED will work without modification across all platforms supported by ArmbianIO. I suspect WiringPi https://github.com/WiringPi/WiringPi-Python would be better suited using ctypes as well after looking at the interface file. I fell for the Swig trap by the allure of simple code generation, but it generates unusable shit turds when it hits pointers in C (C++ seems to be handled better). I ended up using JNA for Java which is like ctypes in that respect.

Share this post


Link to post
Share on other sites

It's nice seeing your project growing. :) 

 

Did you ever thought about a wrapper for JS/NodeRed? I don't know how much efforts it needs but toggeling GPIOs from a standard Node could be a really cool function. 

 

btw. I merged parts from the H5 thread here, cause I thought it makes more sense to have it here, in case you don't like it, just give me a PM and I roll it back.. :P 

Share this post


Link to post
Share on other sites
(edited)
Spoiler

 

On 15.1.2018 at 10:11 PM, Larry Bank said:

A new wrinkle to this idea. I've been working with Arduinos lately and thought it would be useful to extend the ArmbianIO concept to use them as "slave" interfaces for sensors/displays/etc. This is an experiment I'm working on and would like some feedback. The idea is that the ArmbianIO API can be used identically on Windows/Mac/Linux. On a remote setup, an Arduino will be used as an I/O slave listening for commands over the serial port. The ArmbianIO you compile on your PC will translate the I2C/SPI/GPIO functions into strings of commands/data over the serial port. Below is a video of my https://github.com/bitbank2/oled_example project running on my Mac and the same exact C code running on my Orange Pi Lite board next to it:

 

 

Please let me know your thoughts.

Nice idea. Could be useful for the TV-Boxes too, at least for some special use cases.

Edited by Tido
added spoiler

Share this post


Link to post
Share on other sites

I've changed the way the Python wrapper is generated using ctypesgen instead of Swig. This makes the shared library much smaller because it doesn't have any Swig junk linked in. It's basically just a shared version of what @Larry Bank's make builds with the static library (maybe we should add an #IFDEF for that, so I don't have to compile it). There no need to load the library in your code since ctypesgen handles that in the armbianio.py it creates. Your Python code is more elegant and there's no mixing Swig shit code with ctypes or weirdo interface files just to deal with pointers. I'm going to generate the JNA code as well for Java just so I don't have to maintain the interface file if the underlying C API changes. Not sure about JavaScript yet, but if I can find a generator that deals with pointers well then maybe I'll try that next. Here's the obligatory Button program using a callback:

import time
from armbianio.armbianio import *

# Simple callback displays pin and value
def buttonCallback(iPin, iEdge):
    print "Button state: pin = %d, value = %d" % (iPin, iEdge)

# Detect SBC
rc = AIOInit()
if rc == 1:
    # Function returns char array
    print "Running on a %s" % AIOGetBoardName();
    if AIOHasButton():
        button = 0
        # Button callback
        AIOAddGPIOCallback(button, EDGE_BOTH, AIOCALLBACK(buttonCallback));
        print "Press/release button a few times\n"
        time.sleep(10)
        # Remove callback
        AIORemoveGPIO(0)
    else:
        print "%s does not have a button" % AIOGetBoardName();
    AIOShutdown()
else:
    print "AIOInit error"

 

Share this post


Link to post
Share on other sites

@Larry Bank hit up this guy >>> https://github.com/rm-hull <<< He has very similar projects to what your working on, ie: universal SBC's wrappers, except mainly for screens. He has one repo "OPi.GPIO" that aims to accomplish something similar to ArmbianIO project but is limited to OPi as you can imagine. He has recent commits that suggest branching out into NanoPi (Duo) territory though.

 

I talked to him awhile back, pretty cool dude but seems pretty busy and the OPi.GPIO isn't his main focus. In any case this is all to say, without looking at your source and knowing what you do/don't have, maybe he has some goods you can snag.

All in all. Awesome work. Had this idea for a long time, but lack the hardware/expertise to do it (this was as far as I could go) but it's awesome to see you follow up bitbank with ArmbianIO. Keep it up. I'll absolutely be sending you some beer money when I get the chance.

Share this post


Link to post
Share on other sites
On 12/19/2017 at 6:24 PM, tkaiser said:

 

Please check /proc/device-tree/model (applies also to all boards Armbian supports and there should be even a way to use a somewhat similar method at least with Allwinner legacy kernel since I tried some time ago to make fex contents compatible with the DT 'model name' mainline kernel uses for the same devices)

This looks like a solution for 4.x kernel, but what about supporting 3.x? There doesn't seem to be any board-specific info in the /proc directory.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
7 7