Discussion:
using libgpio to bitbang LCDs!
Adrian Chadd
2015-04-12 00:11:47 UTC
Permalink
Hi!

I just ported an adafruit LCD driver to FreeBSD. This was a pretty trivial task:

* convert C++ to C, which was done primarily to not rely on the arduino-isms;
* use libgpio to bitbang the SPI bus needed to write to the LCD.

It worked third time. First was "oh it runs on 5v power and 3.3v
signaling", and I had it hooked up to 3.3. Second was "Oh, I haven't
set the pins to be output pins yet." Third time worked - just slowly.

However - using libgpio was just pleasant. Get a handle, set the pin
config, set the pins high/low. It was pretty damned wonderful.

It turns out that to fill the screen with individual pixel writes
takes quite a few seconds pinning my AR9331 CPU doing ~ 190,000
syscalls a second. Ian's suggested something sensible - a bulk data
ioctl() that can bit bang a series of GPIO pins in the kernel. Ie, one
syscall, a big chunk of data with instructions and timings.

The other interesting thing would be a kind of bulk pin set/get - ie,
instead of doing rmw for one pin at a time, communicate down masks of
pins to do together.

There are some devices (eg these LCDs) that allow you to treat it as a
6800/8080 MCU and do 8 bit data reads/writes, so being able to do that
via the GPIO interface would be nice. The arduino API doesn't do this,
so people (and I'm not making this up) will bitshift a byte into
different GPIO pin set/get, rather than use an 8 bit port as an 8 bit
port.

I'll put the code up soon in case anyone wants to start poking these
embedded LCDs from FreeBSD.

* = Carambola 2 (AR9331) with GPIO pins attached, to an Adafruit
SSD1331 96x64 OLED display.
Rui Paulo
2015-04-12 01:00:46 UTC
Permalink
Post by Adrian Chadd
Hi!
* convert C++ to C, which was done primarily to not rely on the
arduino-isms; * use libgpio to bitbang the SPI bus needed to write to the
LCD.
It worked third time. First was "oh it runs on 5v power and 3.3v
signaling", and I had it hooked up to 3.3. Second was "Oh, I haven't
set the pins to be output pins yet." Third time worked - just slowly.
However - using libgpio was just pleasant. Get a handle, set the pin
config, set the pins high/low. It was pretty damned wonderful.
It turns out that to fill the screen with individual pixel writes
takes quite a few seconds pinning my AR9331 CPU doing ~ 190,000
syscalls a second. Ian's suggested something sensible - a bulk data
ioctl() that can bit bang a series of GPIO pins in the kernel. Ie, one
syscall, a big chunk of data with instructions and timings.
Since this is an LCD, you probably want a way to export the GPIO bank via mmap
with write-combining enabled. It's not really a safe operation as it could
hang the GPIO driver, but it could be useful.
Post by Adrian Chadd
The other interesting thing would be a kind of bulk pin set/get - ie,
instead of doing rmw for one pin at a time, communicate down masks of
pins to do together.
I think that's sensible and could be done via a separate (new) ioctl.
--
Rui Paulo
Luiz Otavio O Souza
2015-04-12 14:45:40 UTC
Permalink
Post by Rui Paulo
Post by Adrian Chadd
Hi!
* convert C++ to C, which was done primarily to not rely on the
arduino-isms; * use libgpio to bitbang the SPI bus needed to write to the
LCD.
It worked third time. First was "oh it runs on 5v power and 3.3v
signaling", and I had it hooked up to 3.3. Second was "Oh, I haven't
set the pins to be output pins yet." Third time worked - just slowly.
However - using libgpio was just pleasant. Get a handle, set the pin
config, set the pins high/low. It was pretty damned wonderful.
It turns out that to fill the screen with individual pixel writes
takes quite a few seconds pinning my AR9331 CPU doing ~ 190,000
syscalls a second. Ian's suggested something sensible - a bulk data
ioctl() that can bit bang a series of GPIO pins in the kernel. Ie, one
syscall, a big chunk of data with instructions and timings.
Since this is an LCD, you probably want a way to export the GPIO bank via mmap
with write-combining enabled. It's not really a safe operation as it could
hang the GPIO driver, but it could be useful.
Post by Adrian Chadd
The other interesting thing would be a kind of bulk pin set/get - ie,
instead of doing rmw for one pin at a time, communicate down masks of
pins to do together.
I think that's sensible and could be done via a separate (new) ioctl.
I've patches for this (bank read and writing), it is pretty simple and
should not block other approaches (mmap, bulk transfers, ...).

Luiz

Adrian Chadd
2015-04-12 06:45:55 UTC
Permalink
Hi,

The library source code and a demo program is available here:

https://github.com/erikarn/freebsd-liblcd

It includes the wiring needed to hook the example OLED board up
(http://www.adafruit.com/products/684) to a Carambola 2 evaluation
board.

Anything you can get 5v and 5 GPIO pins from will work. (Well, as long
as there's also libgpio / gpio API support for your device..)



-adrian
Slawa Olhovchenkov
2015-04-12 08:44:38 UTC
Permalink
Post by Adrian Chadd
Hi!
* convert C++ to C, which was done primarily to not rely on the arduino-isms;
* use libgpio to bitbang the SPI bus needed to write to the LCD.
It worked third time. First was "oh it runs on 5v power and 3.3v
signaling", and I had it hooked up to 3.3. Second was "Oh, I haven't
set the pins to be output pins yet." Third time worked - just slowly.
However - using libgpio was just pleasant. Get a handle, set the pin
config, set the pins high/low. It was pretty damned wonderful.
It turns out that to fill the screen with individual pixel writes
takes quite a few seconds pinning my AR9331 CPU doing ~ 190,000
syscalls a second. Ian's suggested something sensible - a bulk data
ioctl() that can bit bang a series of GPIO pins in the kernel. Ie, one
syscall, a big chunk of data with instructions and timings.
May be best choise is write() or netmap-like interface?
Loading...