Skip to content

Commit

Permalink
o Make slowdown of GPIO switchable. Make it default off, because the
Browse files Browse the repository at this point in the history
  old Raspberry Pis should typically do fine (but their performance hurts
  a lot if this is switched on).
o Exposes the setting experimentally added in issue hzeller#16 in the Makefile.
o Update README describing what to do in these cases and how to switch
  it on.
  • Loading branch information
hzeller committed Mar 5, 2015
1 parent 6212dc6 commit cde792d
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 32 deletions.
56 changes: 39 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,21 +206,6 @@ Then, you can run it with any common image format:

It also supports the standard options to specify the connected
displays (`-r`, `-c`, `-P`).

**CPU use**

These displays need to be updated constantly to show an image with PWMed
LEDs. For one 32x32 display, every second about 500'000 pixels have to be
updated. We can't use any hardware support to do that - thus the constant
CPU use on an RPi is roughly 30%. Keep that in mind if you plan to run other
things on this computer.

Also, the output quality is suceptible to other heavy tasks running on that
computer as the precise timing needed might be slipping. Even if the system is
otherwise idle, you might see occasional brightness variations in the darker
areas of your picture.
(Even with realtime extensions enabled in Linux, this is still a (smaller)
problem).

Chaining, parallel chains and coordinate system
------------------------------------------------
Expand Down Expand Up @@ -408,12 +393,34 @@ guidelines:
- If you still see noise, increase the voltage sligthly above 5V. But note,
this is typically only a symptom of too thin traces.

Help, some pixels are not displayed properly
--------------------------------------------
Some panels don't handle the 3.3V logic level well, in particular with
faster Raspberry Pis. This results in artifacts like randomly showing up pixels
or parts of the whole having 'static'.

If you encounter this, try these things

- Make sure to have as short as possible flat-cables connecting your
Raspberry Pi with the LED panel.

- Use an adapter board with a bus-driver that acts as level shifter between
3.3V and 5V. You can find [active adapter PCBs](./adapter/) in a
subdirectory of this project. Also, Adafruit made a HAT that has level
shifters

- If you can't implement the above things, or still have problems, you can
slow down the GPIO writing a bit. This will of course reduce the
frame-rate. Uncomment the following line in the [lib/Makefile](lib/Makefile)

#DEFINES+=-DRGB_SLOWDOWN_GPIO # remove '#' in the beginning

Inverted Colors ?
-----------------
There are some displays out there that use inverse logic for the colors. You
notice that your image looks like a 'negative'. In that case, uncomment the
folling `DEFINES` line in `lib/Makefile` by removing the `#` at the beginning
of the line.
folling `DEFINES` line in [lib/Makefile](./lib/Makefile) by removing the `#`
at the beginning of the line.

#DEFINES+=-DINVERSE_RGB_DISPLAY_COLORS # remove '#' in the beginning

Expand Down Expand Up @@ -442,6 +449,21 @@ Also, there is an 'output enable' which switches if LEDs are on at all.
Since LEDs can only be on or off, we have to do our own PWM by constantly
clocking in pixels.

**CPU use**

These displays need to be updated constantly to show an image with PWMed
LEDs. For one 32x32 display, every second about 500'000 pixels have to be
updated. We can't use any hardware support to do that - thus the constant
CPU use on an RPi is roughly 30%. Keep that in mind if you plan to run other
things on this computer (This is less noticable on Raspberry Pi, Version 2).

Also, the output quality is suceptible to other heavy tasks running on that
computer as the precise timing needed might be slipping. Even if the system is
otherwise idle, you might see occasional brightness variations in the darker
areas of your picture.
(Even with realtime extensions enabled in Linux, this is still a (smaller)
problem).

Limitations
-----------
If using higher resolution color (This code supports up to 24bpp @3x11 bit PWM),
Expand Down
17 changes: 2 additions & 15 deletions include/gpio.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@

#include <stdint.h>

// The new RPi is often too fast for noise-troubled LED panels. Slow it down.
#define RGB_SLOWDOWN_GPIO 1

// Putting this in our namespace to not collide with other things called like
// this.
namespace rgb_matrix {
Expand Down Expand Up @@ -49,20 +46,10 @@ class GPIO {
uint32_t InitOutputs(uint32_t outputs);

// Set the bits that are '1' in the output. Leave the rest untouched.
inline void SetBits(uint32_t value) {
gpio_port_[0x1C / sizeof(uint32_t)] = value;
#if RGB_SLOWDOWN_GPIO
gpio_port_[0x1C / sizeof(uint32_t)] = value;
#endif
}
void SetBits(uint32_t value);

// Clear the bits that are '1' in the output. Leave the rest untouched.
inline void ClearBits(uint32_t value) {
gpio_port_[0x28 / sizeof(uint32_t)] = value;
#if RGB_SLOWDOWN_GPIO
gpio_port_[0x28 / sizeof(uint32_t)] = value;
#endif
}
void ClearBits(uint32_t value);

// Write all the bits of "value" mentioned in "mask". Leave the rest untouched.
inline void WriteMaskedBits(uint32_t value, uint32_t mask) {
Expand Down
19 changes: 19 additions & 0 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@
OBJECTS=gpio.o led-matrix.o framebuffer.o thread.o bdf-font.o graphics.o
TARGET=librgbmatrix.a

###
# After you change any of the following DEFINES, make sure to 'make clean'
# and make again
###

# The signal can be too fast for some LED panels, in particular with newer
# (faster) Raspberry Pi 2s.
# In these cases, you want to make sure that
# - The cables are short enough from the GPIO header to the panel.
# - Maybe use an active level shifter and bus driver, for instance by building
# up one of the adapter-PCBs in the ../adapter/ directory or use
# the Adafruit HAT. The output drivers of the GPIO are not really good
# in driving long cables - this will improve the situation.
#
# If the above fails or you can't implement them, try uncommenting the
# following line and recompile; it will slow down GPIO, but will as well reduce
# the frame-rate.
#DEFINES+=-DRGB_SLOWDOWN_GPIO

# Uncomment to allow to use up to three parallel boards.
# This will only work on the plus models or RPi2 with 40 GPIO pins.
#
Expand Down
14 changes: 14 additions & 0 deletions lib/gpio.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,20 @@ bool GPIO::Init() {
return Timers::Init();
}

void GPIO::SetBits(uint32_t value) {
gpio_port_[0x1C / sizeof(uint32_t)] = value;
#ifdef RGB_SLOWDOWN_GPIO
gpio_port_[0x1C / sizeof(uint32_t)] = value;
#endif
}

void GPIO::ClearBits(uint32_t value) {
gpio_port_[0x28 / sizeof(uint32_t)] = value;
#ifdef RGB_SLOWDOWN_GPIO
gpio_port_[0x28 / sizeof(uint32_t)] = value;
#endif
}

// ----------
// TODO: timing needs to be improved. It is jittery due to the nature of running
// in a non-realtime operating system, and apparently the nanosleep() does not
Expand Down

0 comments on commit cde792d

Please sign in to comment.