Skip to content

Commit

Permalink
Updating from upstream (#7)
Browse files Browse the repository at this point in the history
* Added delay to ensure reset time being met with low led counts (jgarff#157)

* Fix includes as per jgarff#178 (jgarff#189)

* clean up doco and strandtest (jgarff#187)

* updated documentation on GPIO usage
strandtest now defaults to GRB colour order
added version.h to gitignore

* updated python readme

* more README cleanup

* added notes on spi max transfer size

* Fix freeze after running for long time  (jgarff#197)

* Whitespace cleanup

* Move channel_protocol_time so it handles 32 bit Color LEDs.

* Fix a freezing issue when running for a long time.

When current_timestamp overflowed 2^64, rolling back to 0 and ws2811->render_wait_until had not, this caused an incredibly long usleep in ws2811_render.

* Update README.md (jgarff#191)

* Update README.md

* updated spi buffer size location

* Add -lrt link flag for systems with older glibc (jgarff#195)

* Fix 32-bit overflow in get_microsecond_timestamp(). (jgarff#206)

On Raspbian systems, the tv_sec member of struct timespec is 32 bits
wide.  get_microsecond_timestamp() was overflowing in 32-bit
arithmetic on this member.  This causes the time that it returns to
jump ahead by many thousands of years at uptime = 35 minutes, 48
seconds.  (While the starting point for CLOCK_MONOTONIC_RAW is
unspecified, it seems to track system uptime in practice.)

This overflow didn't cause noticeable problems for me--ws2811_render()
skips the sleep when it thinks such a huge amount time has
elapsed--but it could possibly result in rarely-occurring skipped
frames if the WS2811 reset time isn't effectively honored by
ws2811_render().

* Add TOOLCHAIN option for cross compilation (jgarff#213)

Use this option if you want to cross-compile the library.
Typical usage is:

  scons TOOLCHAIN=arm-linux-gnueabihf

* Add -Wextra compile option and adapt code to suppress warnings (jgarff#214)

The changes in code are mostly type casts between int ann unsigned.

* Add shared library rasbpian package builder.  The package is not built by
default.  To generate the package you need:

- The dpkg-deb utility.
- Use "scons deb" to generate the package.

* Merge user-settable gamma correction into master (jgarff#216)

Merge user-settable gamma correction into master

* Bug fixes for Stretch and Compute Module support (jgarff#222)

* Bug fixes

Missing aligned(4) attribute in pcm.h makes the PCM case failing under
Stretch, due to a newer version of gcc (6.x).
Also fixed a bug in check_hwver_and_gpionum, so original Model A is
recognised.

* README, using SPI on RPi3

Added note to change the core frequency to 250 MHz when using SPI on
RPi 3.

* README fix

* Add support for Compute Module 1 and 3

* Fix undefined clock_gettime symbol

* add missing memory allocation for SPI mode (jgarff#231)

* added Ctrl-C handler to turn off all LEDs on exit (jgarff#140)

* added Ctrl-C handler to turn off all LEDs on exit

* added option -c

* Fix for segmentation fault on exit for Python API (jgarff#239)

Remove useless __del__ because the cleanup() function gets called by
atexit().
Remove ws.ws2811_fini() call which causes the SEGFAULT on exit.
Python does not complain about the memory leak in this way.

* Add support for new A+ hardware.

* Change default DMA channel to safe choice (10) (jgarff#253)

add warning on README.md

* Add getBrightness for brightness feedback from the buffer (jgarff#248)

* Instructions to install the Python library (jgarff#254)

Solving issue jgarff#142

* Fix for non-root users & SPI (jgarff#257)

* Fix for non-root users can use SPI

* use DEFINE'd device strings

also add a note to the readme

* Basic Golang Examples (jgarff#256)

* Added golang example

* Added basic README for golang examples. Added os exits for errors during color wipes for golang examples

* Fix the default DMA in python code (jgarff#266)

DMA 5 causes file system errors on PI 3

* Fixed typo in README.md (jgarff#273)

Was perusing recent commits and saw this.

* clarify electrical notes (jgarff#264)

* Fixed strandtest.py (jgarff#258)

* Fixed keyboardinterrupt, indentation inconsistency, & a few other minor bugs.  Added shebang.

* Fixed KeyboardInterrupt.  Again.

* KeyboardInterrupt works now.  For sure.

* Tabs to spaces, removed redundant signal handling

* Removed unused sys module import

* Added Raspberry Pi 3 B+ (jgarff#276)

* Added Pi 3 B+

* Remove unused import
  • Loading branch information
penfold42 authored and brindosch committed Apr 5, 2018
1 parent f580777 commit 6c5ade9
Show file tree
Hide file tree
Showing 31 changed files with 655 additions and 179 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.sconsign.dblite
version.h
*.pyc
test
newtest
Expand Down
9 changes: 9 additions & 0 deletions DEBIAN/control
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package: libws2811
Version: 1.1.0-1
Section: base
Priority: optional
Architecture: armhf
Depends:
Maintainer: Jeremy Garff (jer@jers.net)
Description: Raspberry Pi WS281X Library
LED Control Library for the Raspberry Pi.
45 changes: 45 additions & 0 deletions DEBIAN/postinst
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/sh

set -e

# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package

# source debconf library
. /usr/share/debconf/confmodule

# Source dbconfig-common functions
if [ -f /usr/share/dbconfig-common/dpkg/postinst.pgsql ]; then
. /usr/share/dbconfig-common/dpkg/postinst.pgsql
fi

case "$1" in

configure)
ldconfig
;;

abort-upgrade|abort-remove|abort-deconfigure)
exit 0
;;

*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;

esac

db_stop

exit 0
~
45 changes: 45 additions & 0 deletions DEBIAN/postrm
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/bin/sh

set -e

# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package

# source debconf library
. /usr/share/debconf/confmodule

# Source dbconfig-common functions
if [ -f /usr/share/dbconfig-common/dpkg/postinst.pgsql ]; then
. /usr/share/dbconfig-common/dpkg/postinst.pgsql
fi

case "$1" in

remove)
ldconfig
;;

abort-upgrade|abort-remove|abort-deconfigure)
exit 0
;;

*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;

esac

db_stop

exit 0
~
44 changes: 44 additions & 0 deletions DEBIAN/prerm
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/bin/sh

set -e

# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package

# source debconf library
. /usr/share/debconf/confmodule

# Source dbconfig-common functions
if [ -f /usr/share/dbconfig-common/dpkg/postinst.pgsql ]; then
. /usr/share/dbconfig-common/dpkg/postinst.pgsql
fi

case "$1" in

remove|upgrade|deconfigure)
;;

abort-upgrade|abort-remove|abort-deconfigure)
exit 0
;;

*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;

esac

db_stop

exit 0

112 changes: 94 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ Userspace Raspberry Pi library for controlling WS281X LEDs.
This includes WS2812 and SK6812RGB RGB LEDs
Preliminary support is now included for SK6812RGBW LEDs (yes, RGB + W)
The LEDs can be controlled by either the PWM (2 independent channels)
or PCM controller (1 channel) or the SPI interfacei (1 channel).
or PCM controller (1 channel) or the SPI interface (1 channel).

### Background:

The BCM2835 in the Raspberry Pi has both a PWM and a PCM module that
are well suited to driving individually controllable WS281X LEDs.
Using the DMA, PWM or PCM FIFO, and serial mode in the PWM, it's
possible to control almost any number of WS281X LEDs in a chain connected
to the appropirate output pin.
For SPI the Raspbian spidev driver is used (/dev/spi0.0).
to the appropriate output pin.
For SPI the Raspbian spidev driver is used (`/dev/spidev0.0`).
This library and test program set the clock rate to 3X the desired output
frequency and creates a bit pattern in RAM from an array of colors where
each bit is represented by 3 bits as follows.
Expand All @@ -23,13 +23,44 @@ each bit is represented by 3 bits as follows.
Bit 0 - 1 0 0


### Hardware:
### GPIO Usage:

WS281X LEDs are generally driven at 5V, which requires that the data
signal be at the same level. Converting the output from a Raspberry
Pi GPIO/PWM to a higher voltage through a level shifter is required.
The GPIOs that can be used are limited by the hardware of the Pi and will
vary based on the method used to drive them (PWM, PCM or SPI).
Beware that the GPIO numbers are not the same as the physical pin numbers
on the header.

It is possible to run the LEDs from a 3.3V - 3.6V power source, and
PWM:
```
PWM0, which can be set to use GPIOs 12, 18, 40, and 52.
Only 12 (pin 32) and 18 (pin 12) are available on the B+/2B/3B
PWM1 which can be set to use GPIOs 13, 19, 41, 45 and 53.
Only 13 is available on the B+/2B/PiZero/3B, on pin 33
```

PCM:
```
PCM_DOUT, which can be set to use GPIOs 21 and 31.
Only 21 is available on the B+/2B/PiZero/3B, on pin 40.
```

SPI:
```
SPI0-MOSI is available on GPIOs 10 and 38.
Only GPIO 10 is available on all models.
See also note for RPi 3 below.
```


### Power and voltage requirements

WS281X LEDs are generally driven at 5V. Depending on your actual
LED model and data line length you might be able to successfully drive
the data input with 3.3V. However in the general case you probably
want to use a level shifter to convert from the Raspberry Pi GPIO/PWM to 5V.

It is also possible to run the LEDs from a 3.3V - 3.6V power source, and
connect the GPIO directly at a cost of brightness, but this isn't
recommended.

Expand All @@ -43,19 +74,41 @@ reponsibility for damage, harm, or mistakes.

### Build:

- Install Scons (on raspbian, apt-get install scons).
- Make sure to adjust the parameters in main.c to suit your hardare.
- Install Scons (on raspbian, `apt-get install scons`).
- Make sure to adjust the parameters in main.c to suit your hardware.
- Signal rate (400kHz to 800kHz). Default 800kHz.
- ledstring.invert=1 if using a inverting level shifter.
- Width and height of LED matrix (height=1 for LED string).
- Type 'scons' from inside the source directory.

### Running:

- Type 'sudo scons'.
- Type 'sudo ./test' (default uses PWM channel 0).
- That's it. You should see a moving rainbow scroll across the
display.
- More options are available, ./test -h should show them:
```
./test version 1.1.0
Usage: ./test
-h (--help) - this information
-s (--strip) - strip type - rgb, grb, gbr, rgbw
-x (--width) - matrix width (default 8)
-y (--height) - matrix height (default 8)
-d (--dma) - dma channel to use (default 10)
-g (--gpio) - GPIO to use
If omitted, default is 18 (PWM0)
-i (--invert) - invert pin output (pulse LOW)
-c (--clear) - clear matrix on exit.
-v (--version) - version information
```

### Important warning about DMA channels

You must make sure that the DMA channel you choose to use for the LEDs is not [already in use](https://www.raspberrypi.org/forums/viewtopic.php?p=609380#p609380) by the operating system.

For example, **using DMA channel 5 [will cause](https://github.com/jgarff/rpi_ws281x/issues/224) filesystem corruption** on the Raspberry Pi 3 Model B.

The default DMA channel (10) should be safe for the Raspberry Pi 3 Model B, but this may change in future software releases.

### Limitations:

Expand All @@ -64,13 +117,21 @@ reponsibility for damage, harm, or mistakes.
Since this library and the onboard Raspberry Pi audio
both use the PWM, they cannot be used together. You will need to
blacklist the Broadcom audio kernel module by creating a file
/etc/modprobe.d/snd-blacklist.conf with
`/etc/modprobe.d/snd-blacklist.conf` with

blacklist snd_bcm2835

If the audio device is still loading after blacklisting, you may also
need to comment it out in the /etc/modules file.

On headless systems you may also need to force audio through hdmi
Edit config.txt and add:

hdmi_force_hotplug=1
hdmi_force_edid_audio=1

A reboot is required for this change to take effect

Some distributions use audio by default, even if nothing is being played.
If audio is needed, you can use a USB audio device instead.

Expand All @@ -84,10 +145,25 @@ uses the PCM hardware, but you can use analog audio.
When using SPI the ledstring is the only device which can be connected to
the SPI bus. Both digital (I2S/PCM) and analog (PWM) audio can be used.

Many distributions have a maximum SPI transfer of 4096 bytes. This can be
changed in `/boot/cmdline.txt` by appending
```
spidev.bufsiz=32768
```
On a RPi 3 you have to change the GPU core frequency to 250 MHz, otherwise
the SPI clock has the wrong frequency.
Do this by adding the following line to /boot/config.txt and reboot.
```
core_freq=250
```

SPI requires you to be in the `gpio` group if you wish to control your LEDs
without root.

### Comparison PWM/PCM/SPI

Both PWM and PCM use DMA transfer to output the control signal for the LEDs.
The max size of a DMA transfer is 65536 bytes. SInce each LED needs 12 bytes
The max size of a DMA transfer is 65536 bytes. Since each LED needs 12 bytes
(4 colors, 8 symbols per color, 3 bits per symbol) this means you can
control approximately 5400 LEDs for a single strand in PCM and 2700 LEDs per string
for PWM (Only PWM can control 2 independent strings simultaneously)
Expand All @@ -103,14 +179,14 @@ When controlling a LED string of 240 LEDs the CPU load on the original Pi 2 (BCM

### Usage:

The API is very simple. Make sure to create and initialize the ws2811_t
structure as seen in main.c. From there it can be initialized
by calling ws2811_init(). LEDs are changed by modifying the color in
the .led[index] array and calling ws2811_render().
The API is very simple. Make sure to create and initialize the `ws2811_t`
structure as seen in [`main.c`](main.c). From there it can be initialized
by calling `ws2811_init()`. LEDs are changed by modifying the color in
the `.led[index]` array and calling `ws2811_render()`.
The rest is handled by the library, which either creates the DMA memory and
starts the DMA for PWM and PCM or prepares the SPI transfer buffer and sends
it out on the MISO pin.

Make sure to hook a signal handler for SIGKILL to do cleanup. From the
handler make sure to call ws2811_fini(). It'll make sure that the DMA
handler make sure to call `ws2811_fini()`. It'll make sure that the DMA
is finished before program execution stops and cleans up after itself.
32 changes: 32 additions & 0 deletions SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,35 @@ for src in srcs:
test = tools_env.Program('test', objs + tools_env['LIBS'])

Default([test, ws2811_lib])

package_version = "1.1.0-1"
package_name = 'libws2811_%s' % package_version

debian_files = [
'DEBIAN/control',
'DEBIAN/postinst',
'DEBIAN/prerm',
'DEBIAN/postrm',
]

package_files_desc = [
[ '/usr/lib', ws2811_slib ],
]

package_files = []
for target in package_files_desc:
package_files.append(tools_env.Install(package_name + target[0], target[1]))

for deb_file in debian_files:
package_files.append(
tools_env.Command('%s/%s' % (package_name, deb_file), deb_file, [
Copy("$TARGET", "$SOURCE"),
Chmod("$TARGET", 0755)
])
)

package = tools_env.Command('%s.deb' % package_name, package_files,
'cd %s; dpkg-deb --build %s' % (Dir('.').abspath, package_name));

Alias("deb", package)

Loading

0 comments on commit 6c5ade9

Please sign in to comment.