Actual code

master
Skylten 5 years ago
parent 6ad76786b7
commit 205ccbce1d

@ -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.

@ -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
~

@ -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
~

@ -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

@ -0,0 +1,24 @@
Copyright (c) 2014, jgarff
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -0,0 +1,95 @@
#
# SConscript
#
# Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted
# provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
# 3. Neither the name of the owner nor the names of its contributors may be used to endorse
# or promote products derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
Import(['clean_envs'])
tools_env = clean_envs['userspace'].Clone()
# Build Library
lib_srcs = Split('''
mailbox.c
ws2811.c
pwm.c
pcm.c
dma.c
rpihw.c
''')
version_hdr = tools_env.Version('version')
ws2811_lib = tools_env.Library('libws2811', lib_srcs)
tools_env['LIBS'].append(ws2811_lib)
# Shared library (if required)
ws2811_slib = tools_env.SharedLibrary('libws2811', lib_srcs)
# Test Program
srcs = Split('''
main.c
''')
objs = []
for src in srcs:
objs.append(tools_env.Object(src))
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)

@ -0,0 +1,76 @@
#
# SConstruct
#
# Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted
# provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
# 3. Neither the name of the owner nor the names of its contributors may be used to endorse
# or promote products derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import os
opts = Variables()
opts.Add(BoolVariable('V',
'Verbose build',
False))
opts.Add('TOOLCHAIN',
'Set toolchain for cross compilation (e.g. arm-linux-gnueabihf)',
'')
platforms = [
[
'userspace', # Target Name
[ 'linux', 'version' ], # Scons tool (linux, avr, etc.)
{ # Special environment setup
'CPPPATH' : [
],
'LINKFLAGS' : [
"-lrt",
],
},
],
]
clean_envs = {}
for platform, tool, flags in platforms:
env = Environment(
options = opts,
tools = tool,
toolpath = ['.'],
ENV = {'PATH' : os.environ['PATH']},
LIBS = [],
)
env.MergeFlags(flags)
clean_envs[platform] = env
Help(opts.GenerateHelpText(clean_envs))
if env['TOOLCHAIN'] != '':
env['CC'] = env['TOOLCHAIN'] + '-gcc'
env['AR'] = env['TOOLCHAIN'] + '-ar'
Export(['clean_envs'])
SConscript('SConscript');

65
clk.h

@ -0,0 +1,65 @@
/*
* clk.h
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __CLK_H__
#define __CLK_H__
typedef struct {
uint32_t ctl;
#define CM_CLK_CTL_PASSWD (0x5a << 24)
#define CM_CLK_CTL_MASH(val) ((val & 0x3) << 9)
#define CM_CLK_CTL_FLIP (1 << 8)
#define CM_CLK_CTL_BUSY (1 << 7)
#define CM_CLK_CTL_KILL (1 << 5)
#define CM_CLK_CTL_ENAB (1 << 4)
#define CM_CLK_CTL_SRC_GND (0 << 0)
#define CM_CLK_CTL_SRC_OSC (1 << 0)
#define CM_CLK_CTL_SRC_TSTDBG0 (2 << 0)
#define CM_CLK_CTL_SRC_TSTDBG1 (3 << 0)
#define CM_CLK_CTL_SRC_PLLA (4 << 0)
#define CM_CLK_CTL_SRC_PLLC (5 << 0)
#define CM_CLK_CTL_SRC_PLLD (6 << 0)
#define CM_CLK_CTL_SRC_HDMIAUX (7 << 0)
uint32_t div;
#define CM_CLK_DIV_PASSWD (0x5a << 24)
#define CM_CLK_DIV_DIVI(val) ((val & 0xfff) << 12)
#define CM_CLK_DIV_DIVF(val) ((val & 0xfff) << 0)
} __attribute__((packed, aligned(4))) cm_clk_t;
/*
* PWM and PCM clock offsets from https://www.scribd.com/doc/127599939/BCM2835-Audio-clocks
*
*/
#define CM_PCM_OFFSET (0x00101098)
#define CM_PWM_OFFSET (0x001010a0)
#endif /* __CLK_H__ */

78
dma.c

@ -0,0 +1,78 @@
/*
* dma.c
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include "dma.h"
// DMA address mapping by DMA number index
static const uint32_t dma_offset[] =
{
DMA0_OFFSET,
DMA1_OFFSET,
DMA2_OFFSET,
DMA3_OFFSET,
DMA4_OFFSET,
DMA5_OFFSET,
DMA6_OFFSET,
DMA7_OFFSET,
DMA8_OFFSET,
DMA9_OFFSET,
DMA10_OFFSET,
DMA11_OFFSET,
DMA12_OFFSET,
DMA13_OFFSET,
DMA14_OFFSET,
DMA15_OFFSET,
};
uint32_t dmanum_to_offset(int dmanum)
{
int array_size = sizeof(dma_offset) / sizeof(dma_offset[0]);
if (dmanum >= array_size)
{
return 0;
}
return dma_offset[dmanum];
}

126
dma.h

@ -0,0 +1,126 @@
/*
* dma.h
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __DMA_H__
#define __DMA_H__
/*
* DMA Control Block in Main Memory
*
* Note: Must start at a 256 byte aligned address.
* Use corresponding register field definitions.
*/
typedef struct
{
uint32_t ti;
uint32_t source_ad;
uint32_t dest_ad;
uint32_t txfr_len;
uint32_t stride;
uint32_t nextconbk;
uint32_t resvd_0x18[2];
} __attribute__((packed, aligned(4))) dma_cb_t;
/*
* DMA register set
*/
typedef struct
{
uint32_t cs;
#define RPI_DMA_CS_RESET (1 << 31)
#define RPI_DMA_CS_ABORT (1 << 30)
#define RPI_DMA_CS_DISDEBUG (1 << 29)
#define RPI_DMA_CS_WAIT_OUTSTANDING_WRITES (1 << 28)
#define RPI_DMA_CS_PANIC_PRIORITY(val) ((val & 0xf) << 20)
#define RPI_DMA_CS_PRIORITY(val) ((val & 0xf) << 16)
#define RPI_DMA_CS_ERROR (1 << 8)
#define RPI_DMA_CS_WAITING_OUTSTANDING_WRITES (1 << 6)
#define RPI_DMA_CS_DREQ_STOPS_DMA (1 << 5)
#define RPI_DMA_CS_PAUSED (1 << 4)
#define RPI_DMA_CS_DREQ (1 << 3)
#define RPI_DMA_CS_INT (1 << 2)
#define RPI_DMA_CS_END (1 << 1)
#define RPI_DMA_CS_ACTIVE (1 << 0)
uint32_t conblk_ad;
uint32_t ti;
#define RPI_DMA_TI_NO_WIDE_BURSTS (1 << 26)
#define RPI_DMA_TI_WAITS(val) ((val & 0x1f) << 21)
#define RPI_DMA_TI_PERMAP(val) ((val & 0x1f) << 16)
#define RPI_DMA_TI_BURST_LENGTH(val) ((val & 0xf) << 12)
#define RPI_DMA_TI_SRC_IGNORE (1 << 11)
#define RPI_DMA_TI_SRC_DREQ (1 << 10)
#define RPI_DMA_TI_SRC_WIDTH (1 << 9)
#define RPI_DMA_TI_SRC_INC (1 << 8)
#define RPI_DMA_TI_DEST_IGNORE (1 << 7)
#define RPI_DMA_TI_DEST_DREQ (1 << 6)
#define RPI_DMA_TI_DEST_WIDTH (1 << 5)
#define RPI_DMA_TI_DEST_INC (1 << 4)
#define RPI_DMA_TI_WAIT_RESP (1 << 3)
#define RPI_DMA_TI_TDMODE (1 << 1)
#define RPI_DMA_TI_INTEN (1 << 0)
uint32_t source_ad;
uint32_t dest_ad;
uint32_t txfr_len;
#define RPI_DMA_TXFR_LEN_YLENGTH(val) ((val & 0xffff) << 16)
#define RPI_DMA_TXFR_LEN_XLENGTH(val) ((val & 0xffff) << 0)
uint32_t stride;
#define RPI_DMA_STRIDE_D_STRIDE(val) ((val & 0xffff) << 16)
#define RPI_DMA_STRIDE_S_STRIDE(val) ((val & 0xffff) << 0)
uint32_t nextconbk;
uint32_t debug;
} __attribute__((packed, aligned(4))) dma_t;
#define DMA0_OFFSET (0x00007000)
#define DMA1_OFFSET (0x00007100)
#define DMA2_OFFSET (0x00007200)
#define DMA3_OFFSET (0x00007300)
#define DMA4_OFFSET (0x00007400)
#define DMA5_OFFSET (0x00007500)
#define DMA6_OFFSET (0x00007600)
#define DMA7_OFFSET (0x00007700)
#define DMA8_OFFSET (0x00007800)
#define DMA9_OFFSET (0x00007900)
#define DMA10_OFFSET (0x00007a00)
#define DMA11_OFFSET (0x00007b00)
#define DMA12_OFFSET (0x00007c00)
#define DMA13_OFFSET (0x00007d00)
#define DMA14_OFFSET (0x00007e00)
#define DMA15_OFFSET (0x00e05000)
#define PAGE_SIZE (1 << 12)
#define PAGE_MASK (~(PAGE_SIZE - 1))
#define PAGE_OFFSET(page) (page & (PAGE_SIZE - 1))
uint32_t dmanum_to_offset(int dmanum);
#endif /* __DMA_H__ */

@ -0,0 +1,28 @@
## Deprecated
This Go code is being phased out and replaced with https://github.com/rpi-ws281x/rpi-ws281x-go
For issues and bugs with (or contributions to) the Go library, please see: https://github.com/rpi-ws281x/rpi-ws281x-go/issues
----
## Run a demo
As this is just a Go wrapper for the library you must clone this into your `$GOPATH` as you would any other Go program.
Your path to the project should be:
```
$GOPATH/src/github.com/jgraff/rpi_ws281x
```
As listed in the `ws2811.go` file ensure to copy `ws2811.h`, `rpihw.h`, and `pwm.h` in a GCC include path (e.g. `/usr/local/include`) and
`libws2811.a` in a GCC library path (e.g. `/usr/local/lib`).
To run the basic example run the following commands:
```
cd golang/examples
go build basic.go
sudo ./basic
```
If everything worked you should see a basic color wipe for the first 16 LEDs on your strip.

@ -0,0 +1,60 @@
package main
import (
"time"
"os"
"fmt"
"github.com/jgarff/rpi_ws281x/golang/ws2811"
)
const (
pin = 18
count = 16
brightness = 255
)
func main() {
defer ws2811.Fini()
err := ws2811.Init(pin, count, brightness)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Press Ctr-C to quit.")
fmt.Println("Creating blue color wipe")
err = colorWipe(uint32(0x000020))
if err != nil {
fmt.Println("Error during wipe " + err.Error())
os.Exit(-1)
}
fmt.Println("Creating red color wipe")
err = colorWipe(uint32(0x002000))
if err != nil {
fmt.Println("Error during wipe " + err.Error())
os.Exit(-1)
}
fmt.Println("Creating green color wipe")
err = colorWipe(uint32(0x200000))
if err != nil {
fmt.Println("Error during wipe " + err.Error())
os.Exit(-1)
}
}
}
func colorWipe(color uint32) error {
for i := 0; i < count; i++ {
ws2811.SetLed(i, color)
err := ws2811.Render()
if err != nil {
ws2811.Clear()
return err
}
time.Sleep(50 * time.Millisecond)
}
return nil
}

@ -0,0 +1,91 @@
// Copyright (c) 2015, Jacques Supcik, HEIA-FR
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the <organization> nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
Interface to ws2811 chip (neopixel driver). Make sure that you have
ws2811.h, rpihw.h, and pwm.h in a GCC include path (e.g. /usr/local/include) and
libws2811.a in a GCC library path (e.g. /usr/local/lib).
See https://github.com/jgarff/rpi_ws281x for instructions
*/
package ws2811
/*
#cgo CFLAGS: -std=c99
#cgo LDFLAGS: -lws2811
#include "ws2811.go.h"
*/
import "C"
import (
"errors"
"fmt"
"unsafe"
)
func Init(gpioPin int, ledCount int, brightness int) error {
C.ledstring.channel[0].gpionum = C.int(gpioPin)
C.ledstring.channel[0].count = C.int(ledCount)
C.ledstring.channel[0].brightness = C.uint8_t(brightness)
res := int(C.ws2811_init(&C.ledstring))
if res == 0 {
return nil
} else {
return errors.New(fmt.Sprintf("Error ws2811.init.%d", res))
}
}
func Fini() {
C.ws2811_fini(&C.ledstring)
}
func Render() error {
res := int(C.ws2811_render(&C.ledstring))
if res == 0 {
return nil
} else {
return errors.New(fmt.Sprintf("Error ws2811.render.%d", res))
}
}
func Wait() error {
res := int(C.ws2811_wait(&C.ledstring))
if res == 0 {
return nil
} else {
return errors.New(fmt.Sprintf("Error ws2811.wait.%d", res))
}
}
func SetLed(index int, value uint32) {
C.ws2811_set_led(&C.ledstring, C.int(index), C.uint32_t(value))
}
func Clear() {
C.ws2811_clear(&C.ledstring)
}
func SetBitmap(a []uint32) {
C.ws2811_set_bitmap(&C.ledstring, unsafe.Pointer(&a[0]), C.int(len(a)*4))
}

@ -0,0 +1,64 @@
/***********************************************************************************
* Copyright (c) 2015, Jacques Supcik, HEIA-FR
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************************/
#include <stdint.h>
#include <string.h>
#include <ws2811.h>
ws2811_t ledstring = {
.freq = 800000,
.dmanum = 10,
.channel = {
[0] = {
.gpionum = 18,
.count = 256,
.invert = 0,
.brightness = 32,
},
[1] = {
.gpionum = 0,
.count = 0,
.invert = 0,
.brightness = 0,
},
},
};
void ws2811_set_led(ws2811_t *ws2811, int index, uint32_t value) {
ws2811->channel[0].leds[index] = value;
}
void ws2811_clear(ws2811_t *ws2811) {
for (int chan = 0; chan < RPI_PWM_CHANNELS; chan++) {
ws2811_channel_t *channel = &ws2811->channel[chan];
memset(channel->leds, 0, sizeof(ws2811_led_t) * channel->count);
}
}
void ws2811_set_bitmap(ws2811_t *ws2811, void* a, int len) {
memcpy(ws2811->channel[0].leds, a, len);
}

108
gpio.h

@ -0,0 +1,108 @@
/*
* gpio.h
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __GPIO_H__
#define __GPIO_H__
typedef struct
{
uint32_t fsel[6]; // GPIO Function Select
uint32_t resvd_0x18;
uint32_t set[2]; // GPIO Pin Output Set
uint32_t resvd_0x24;
uint32_t clr[2]; // GPIO Pin Output Clear
uint32_t resvd_0x30;
uint32_t lev[2]; // GPIO Pin Level
uint32_t resvd_0x3c;
uint32_t eds[2]; // GPIO Pin Event Detect Status
uint32_t resvd_0x48;
uint32_t ren[2]; // GPIO Pin Rising Edge Detect Enable
uint32_t resvd_0x54;
uint32_t fen[2]; // GPIO Pin Falling Edge Detect Enable
uint32_t resvd_0x60;
uint32_t hen[2]; // GPIO Pin High Detect Enable
uint32_t resvd_0x6c;
uint32_t len[2]; // GPIO Pin Low Detect Enable
uint32_t resvd_0x78;
uint32_t aren[2]; // GPIO Pin Async Rising Edge Detect
uint32_t resvd_0x84;
uint32_t afen[2]; // GPIO Pin Async Falling Edge Detect
uint32_t resvd_0x90;
uint32_t pud; // GPIO Pin Pull up/down Enable
uint32_t pudclk[2]; // GPIO Pin Pull up/down Enable Clock
uint32_t resvd_0xa0[4];
uint32_t test;
} __attribute__((packed, aligned(4))) gpio_t;
#define GPIO_OFFSET (0x00200000)
static inline void gpio_function_set(volatile gpio_t *gpio, uint8_t pin, uint8_t function)
{
int regnum = pin / 10;
int offset = (pin % 10) * 3;
uint8_t funcmap[] = { 4, 5, 6, 7, 3, 2 }; // See datasheet for mapping
if (function > 5)
{
return;
}
gpio->fsel[regnum] &= ~(0x7 << offset);
gpio->fsel[regnum] |= ((funcmap[function]) << offset);
}
static inline void gpio_level_set(volatile gpio_t *gpio, uint8_t pin, uint8_t level)
{
int regnum = pin >> 5;
int offset = (pin & 0x1f);
if (level)
{
gpio->set[regnum] = (1 << offset);
}
else
{
gpio->clr[regnum] = (1 << offset);
}
}
static inline void gpio_output_set(volatile gpio_t *gpio, uint8_t pin, uint8_t output)
{
int regnum = pin / 10;
int offset = (pin % 10) * 3;
uint8_t function = output ? 1 : 0; // See datasheet for mapping
gpio->fsel[regnum] &= ~(0x7 << offset);
gpio->fsel[regnum] |= ((function & 0x7) << offset);
}
#endif /* __GPIO_H__ */

@ -0,0 +1,84 @@
#
# linux.py
#
# Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted
# provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
# 3. Neither the name of the owner nor the names of its contributors may be used to endorse
# or promote products derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import SCons
import string
import array
import os
tools = ['gcc', 'g++', 'gnulink', 'ar', 'gas']
def linux_tools(env):
for tool in tools:
env.Tool(tool)
if not env['V']:
env['ARCOMSTR'] = 'AR ${TARGET}'
env['ASCOMSTR'] = 'AS ${TARGET}'
env['CCCOMSTR'] = 'CC ${TARGET}'
env['CXXCOMSTR'] = 'C++ ${TARGET}'
env['LINKCOMSTR'] = 'LINK ${TARGET}'
env['RANLIBCOMSTR'] = 'RANLIB ${TARGET}'
def linux_flags(env):
env.MergeFlags({
'CPPFLAGS' : '''
-fPIC
-g
-O2
-Wall
-Wextra
-Werror
'''.split(),
}),
env.MergeFlags({
'LINKFLAGS' : '''
'''.split()
})
def linux_builders(env):
env.Append(BUILDERS = {
'Program' : SCons.Builder.Builder(
action = SCons.Action.Action('${LINK} -o ${TARGET} ${SOURCES} ${LINKFLAGS}',
'${LINKCOMSTR}'),
),
})
return 1
# The following are required functions by SCons when incorporating through tools
def exists(env):
return 1
def generate(env, **kwargs):
[f(env) for f in (linux_tools, linux_flags, linux_builders)]

@ -0,0 +1,292 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd.
Copyright (c) 2016, Jeremy Garff
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/sysmacros.h>
#include <sys/stat.h>
#include "mailbox.h"
void *mapmem(uint32_t base, uint32_t size, const char *mem_dev) {
uint32_t pagemask = ~0UL ^ (getpagesize() - 1);
uint32_t offsetmask = getpagesize() - 1;
int mem_fd;
void *mem;
mem_fd = open(mem_dev, O_RDWR | O_SYNC);
if (mem_fd < 0) {
perror("Can't open /dev/mem");
return NULL;
}
mem = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, base & pagemask);
if (mem == MAP_FAILED) {
perror("mmap error\n");
return NULL;
}
close(mem_fd);
return (char *)mem + (base & offsetmask);
}
void *unmapmem(void *addr, uint32_t size) {
uint32_t pagemask = ~0UL ^ (getpagesize() - 1);
uintptr_t baseaddr = (uintptr_t)addr & pagemask;
int s;
s = munmap((void *)baseaddr, size);
if (s != 0) {
perror("munmap error\n");
}
return NULL;
}
/*
* use ioctl to send mbox property message
*/
static int mbox_property(int file_desc, void *buf) {
int fd = file_desc;
int ret_val = -1;
if (fd < 0) {
fd = mbox_open();
}
if (fd >= 0) {
ret_val = ioctl(fd, IOCTL_MBOX_PROPERTY, buf);
if (ret_val < 0) {
perror("ioctl_set_msg failed\n");
}
}
if (file_desc < 0) {
mbox_close(fd);
}
return ret_val;
}
uint32_t mem_alloc(int file_desc, uint32_t size, uint32_t align, uint32_t flags) {
int i=0;
uint32_t p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x3000c; // (the tag id)
p[i++] = 12; // (size of the buffer)
p[i++] = 12; // (size of the data)
p[i++] = size; // (num bytes? or pages?)
p[i++] = align; // (alignment)
p[i++] = flags; // (MEM_FLAG_L1_NONALLOCATING)
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
if (mbox_property(file_desc, p) < 0)
return 0;
else
return p[5];
}
uint32_t mem_free(int file_desc, uint32_t handle) {
int i=0;
uint32_t p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x3000f; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
mbox_property(file_desc, p);
return p[5];
}
uint32_t mem_lock(int file_desc, uint32_t handle) {
int i=0;
uint32_t p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x3000d; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;
p[i++] = 0x00000000; // end tag
p[0] = i*sizeof *p; // actual size
if (mbox_property(file_desc, p) < 0)
return ~0;
else
return p[5];
}
uint32_t mem_unlock(int file_desc, uint32_t handle) {
int i=0;
uint32_t p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x3000e; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = handle;
p[i++] = 0x00000000; // end tag
p[0] = i * sizeof(*p); // actual size
mbox_property(file_desc, p);
return p[5];
}
uint32_t execute_code(int file_desc, uint32_t code, uint32_t r0, uint32_t r1,
uint32_t r2, uint32_t r3, uint32_t r4, uint32_t r5) {
int i=0;
uint32_t p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x30010; // (the tag id)
p[i++] = 28; // (size of the buffer)
p[i++] = 28; // (size of the data)
p[i++] = code;
p[i++] = r0;
p[i++] = r1;
p[i++] = r2;
p[i++] = r3;
p[i++] = r4;
p[i++] = r5;
p[i++] = 0x00000000; // end tag
p[0] = i * sizeof(*p); // actual size
mbox_property(file_desc, p);
return p[5];
}
uint32_t qpu_enable(int file_desc, uint32_t enable) {
int i=0;
uint32_t p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x30012; // (the tag id)
p[i++] = 4; // (size of the buffer)
p[i++] = 4; // (size of the data)
p[i++] = enable;
p[i++] = 0x00000000; // end tag
p[0] = i * sizeof(*p); // actual size
mbox_property(file_desc, p);
return p[5];
}
uint32_t execute_qpu(int file_desc, uint32_t num_qpus, uint32_t control,
uint32_t noflush, uint32_t timeout) {
int i = 0;
uint32_t p[32];
p[i++] = 0; // size
p[i++] = 0x00000000; // process request
p[i++] = 0x30011; // (the tag id)
p[i++] = 16; // (size of the buffer)
p[i++] = 16; // (size of the data)
p[i++] = num_qpus;
p[i++] = control;
p[i++] = noflush;
p[i++] = timeout; // ms
p[i++] = 0x00000000; // end tag
p[0] = i * sizeof(*p); // actual size
mbox_property(file_desc, p);
return p[5];
}
int mbox_open(void) {
int file_desc;
char filename[64];
file_desc = open("/dev/vcio", 0);
if (file_desc >= 0) {
return file_desc;
}
// open a char device file used for communicating with kernel mbox driver
sprintf(filename, "/tmp/mailbox-%d", getpid());
unlink(filename);
if (mknod(filename, S_IFCHR|0600, makedev(100, 0)) < 0) {
perror("Failed to create mailbox device\n");
return -1;
}
file_desc = open(filename, 0);
if (file_desc < 0) {
perror("Can't open device file\n");
unlink(filename);
return -1;
}
unlink(filename);
return file_desc;
}
void mbox_close(int file_desc) {
close(file_desc);
}

@ -0,0 +1,49 @@
/*
Copyright (c) 2012, Broadcom Europe Ltd.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <linux/ioctl.h>
#define MAJOR_NUM 100
#define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *)
#define DEV_MEM "/dev/mem"
#define DEV_GPIOMEM "/dev/gpiomem"
int mbox_open(void);
void mbox_close(int file_desc);
unsigned get_version(int file_desc);
unsigned mem_alloc(int file_desc, unsigned size, unsigned align, unsigned flags);
unsigned mem_free(int file_desc, unsigned handle);
unsigned mem_lock(int file_desc, unsigned handle);
unsigned mem_unlock(int file_desc, unsigned handle);
void *mapmem(unsigned base, unsigned size, const char *mem_dev);
void *unmapmem(void *addr, unsigned size);
unsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5);
unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout);
unsigned qpu_enable(int file_desc, unsigned enable);

419
main.c

@ -0,0 +1,419 @@
/*
* newtest.c
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
static char VERSION[] = "XX.YY.ZZ";
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <signal.h>
#include <stdarg.h>
#include <getopt.h>
#include "clk.h"
#include "gpio.h"
#include "dma.h"
#include "pwm.h"
#include "version.h"
#include "ws2811.h"
#define ARRAY_SIZE(stuff) (sizeof(stuff) / sizeof(stuff[0]))
// defaults for cmdline options
#define TARGET_FREQ WS2811_TARGET_FREQ
#define GPIO_PIN 18
#define DMA 10
//#define STRIP_TYPE WS2811_STRIP_RGB // WS2812/SK6812RGB integrated chip+leds
#define STRIP_TYPE WS2811_STRIP_GBR // WS2812/SK6812RGB integrated chip+leds
//#define STRIP_TYPE SK6812_STRIP_RGBW // SK6812RGBW (NOT SK6812RGB)
#define WIDTH 8
#define HEIGHT 8
#define LED_COUNT (WIDTH * HEIGHT)
int width = WIDTH;
int height = HEIGHT;
int led_count = LED_COUNT;
int clear_on_exit = 0;
ws2811_t ledstring =
{
.freq = TARGET_FREQ,
.dmanum = DMA,
.channel =
{
[0] =
{
.gpionum = GPIO_PIN,
.count = LED_COUNT,
.invert = 0,
.brightness = 255,
.strip_type = STRIP_TYPE,
},
[1] =
{
.gpionum = 0,
.count = 0,
.invert = 0,
.brightness = 0,
},
},
};
ws2811_led_t *matrix;
static uint8_t running = 1;
void matrix_render(void)
{
int x, y;
for (x = 0; x < width; x++)
{
for (y = 0; y < height; y++)
{
ledstring.channel[0].leds[(y * width) + x] = matrix[y * width + x];
}
}
}
void matrix_raise(void)
{
int x, y;
for (y = 0; y < (height - 1); y++)
{
for (x = 0; x < width; x++)
{
// This is for the 8x8 Pimoroni Unicorn-HAT where the LEDS in subsequent
// rows are arranged in opposite directions
matrix[y * width + x] = matrix[(y + 1)*width + width - x - 1];
}
}
}
void matrix_clear(void)
{
int x, y;
for (y = 0; y < (height ); y++)
{
for (x = 0; x < width; x++)
{
matrix[y * width + x] = 0;
}
}
}
int dotspos[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
ws2811_led_t dotcolors[] =
{
0x00200000, // red
0x00201000, // orange
0x00202000, // yellow
0x00002000, // green
0x00002020, // lightblue
0x00000020, // blue
0x00100010, // purple
0x00200010, // pink
};
ws2811_led_t dotcolors_rgbw[] =
{
0x00200000, // red
0x10200000, // red + W
0x00002000, // green
0x10002000, // green + W
0x00000020, // blue
0x10000020, // blue + W
0x00101010, // white
0x10101010, // white + W
};
void matrix_bottom(void)
{
int i;
for (i = 0; i < (int)(ARRAY_SIZE(dotspos)); i++)
{
dotspos[i]++;
if (dotspos[i] > (width - 1))
{
dotspos[i] = 0;
}
if (ledstring.channel[0].strip_type == SK6812_STRIP_RGBW) {
matrix[dotspos[i] + (height - 1) * width] = dotcolors_rgbw[i];
} else {
matrix[dotspos[i] + (height - 1) * width] = dotcolors[i];
}
}
}
static void ctrl_c_handler(int signum)
{
(void)(signum);
running = 0;
}
static void setup_handlers(void)
{
struct sigaction sa =
{
.sa_handler = ctrl_c_handler,
};
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
}
void parseargs(int argc, char **argv, ws2811_t *ws2811)
{
int index;
int c;
static struct option longopts[] =
{
{"help", no_argument, 0, 'h'},
{"dma", required_argument, 0, 'd'},
{"gpio", required_argument, 0, 'g'},
{"invert", no_argument, 0, 'i'},
{"clear", no_argument, 0, 'c'},
{"strip", required_argument, 0, 's'},
{"height", required_argument, 0, 'y'},
{"width", required_argument, 0, 'x'},
{"version", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
while (1)
{
index = 0;
c = getopt_long(argc, argv, "cd:g:his:vx:y:", longopts, &index);
if (c == -1)
break;
switch (c)
{
case 0:
/* handle flag options (array's 3rd field non-0) */
break;
case 'h':
fprintf(stderr, "%s version %s\n", argv[0], VERSION);
fprintf(stderr, "Usage: %s \n"
"-h (--help) - this information\n"
"-s (--strip) - strip type - rgb, grb, gbr, rgbw\n"
"-x (--width) - matrix width (default 8)\n"
"-y (--height) - matrix height (default 8)\n"
"-d (--dma) - dma channel to use (default 10)\n"
"-g (--gpio) - GPIO to use\n"
" If omitted, default is 18 (PWM0)\n"
"-i (--invert) - invert pin output (pulse LOW)\n"
"-c (--clear) - clear matrix on exit.\n"
"-v (--version) - version information\n"
, argv[0]);
exit(-1);
case 'D':
break;
case 'g':
if (optarg) {
int gpio = atoi(optarg);
/*
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_DOUT, which can be set to use GPIOs 21 and 31.
Only 21 is available on the B+/2B/PiZero/3B, on pin 40.
SPI0-MOSI is available on GPIOs 10 and 38.
Only GPIO 10 is available on all models.
The library checks if the specified gpio is available
on the specific model (from model B rev 1 till 3B)
*/
ws2811->channel[0].gpionum = gpio;
}
break;
case 'i':
ws2811->channel[0].invert=1;
break;
case 'c':
clear_on_exit=1;
break;
case 'd':
if (optarg) {
int dma = atoi(optarg);
if (dma < 14) {
ws2811->dmanum = dma;
} else {
printf ("invalid dma %d\n", dma);
exit (-1);
}
}
break;
case 'y':
if (optarg) {
height = atoi(optarg);
if (height > 0) {
ws2811->channel[0].count = height * width;
} else {
printf ("invalid height %d\n", height);
exit (-1);
}
}
break;
case 'x':
if (optarg) {
width = atoi(optarg);
if (width > 0) {
ws2811->channel[0].count = height * width;
} else {
printf ("invalid width %d\n", width);
exit (-1);
}
}
break;
case 's':
if (optarg) {
if (!strncasecmp("rgb", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_RGB;
}
else if (!strncasecmp("rbg", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_RBG;
}
else if (!strncasecmp("grb", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_GRB;
}
else if (!strncasecmp("gbr", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_GBR;
}
else if (!strncasecmp("brg", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_BRG;
}
else if (!strncasecmp("bgr", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_BGR;
}
else if (!strncasecmp("rgbw", optarg, 4)) {
ws2811->channel[0].strip_type = SK6812_STRIP_RGBW;
}
else if (!strncasecmp("grbw", optarg, 4)) {
ws2811->channel[0].strip_type = SK6812_STRIP_GRBW;
}
else {
printf ("invalid strip %s\n", optarg);
exit (-1);
}
}
break;
case 'v':
fprintf(stderr, "%s version %s\n", argv[0], VERSION);
exit(-1);
case '?':
/* getopt_long already reported error? */
exit(-1);
default:
exit(-1);
}
}
}
int main(int argc, char *argv[])
{
ws2811_return_t ret;
sprintf(VERSION, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO);
parseargs(argc, argv, &ledstring);
matrix = malloc(sizeof(ws2811_led_t) * width * height);
setup_handlers();
if ((ret = ws2811_init(&ledstring)) != WS2811_SUCCESS)
{
fprintf(stderr, "ws2811_init failed: %s\n", ws2811_get_return_t_str(ret));
return ret;
}
while (running)
{
matrix_raise();
matrix_bottom();
matrix_render();
if ((ret = ws2811_render(&ledstring)) != WS2811_SUCCESS)
{
fprintf(stderr, "ws2811_render failed: %s\n", ws2811_get_return_t_str(ret));
break;
}
// 15 frames /sec
usleep(1000000 / 15);
}
if (clear_on_exit) {
matrix_clear();
matrix_render();
ws2811_render(&ledstring);
}
ws2811_fini(&ledstring);
printf ("\n");
return ret;
}

127
pcm.c

@ -0,0 +1,127 @@
/*
* pcm.c
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
* PCM version Copyright (c) 2016 Ton van Overbeek <tvoverbeek @ gmail.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include "pcm.h"
// Mapping of Pin to alternate function for PCM_CLK
const pcm_pin_table_t pcm_pin_clk[] =
{
{
.pinnum = 18,
.altnum = 0,
},
{
.pinnum = 28,
.altnum = 2,
},
};
// Mapping of Pin to alternate function for PCM_FS
const pcm_pin_table_t pcm_pin_fs[] =
{
{
.pinnum = 19,
.altnum = 0,
},
{
.pinnum = 29,
.altnum = 2,
},
};
// Mapping of Pin to alternate function for PCM_DIN
const pcm_pin_table_t pcm_pin_din[] =
{
{
.pinnum = 20,
.altnum = 0,
},
{
.pinnum = 30,
.altnum = 2,
},
};
// Mapping of Pin to alternate function for PCM_DOUT
const pcm_pin_table_t pcm_pin_dout[] =
{
{
.pinnum = 21,
.altnum = 0,
},
{
.pinnum = 31,
.altnum = 2,
},
};
const pcm_pin_tables_t pcm_pin_tables[NUM_PCMFUNS] =
{
{
.pins = pcm_pin_clk,
.count = sizeof(pcm_pin_clk) / sizeof(pcm_pin_clk[0]),
},
{
.pins = pcm_pin_fs,
.count = sizeof(pcm_pin_fs) / sizeof(pcm_pin_fs[0]),
},
{
.pins = pcm_pin_din,
.count = sizeof(pcm_pin_din) / sizeof(pcm_pin_din[0]),
},
{
.pins = pcm_pin_dout,
.count = sizeof(pcm_pin_dout) / sizeof(pcm_pin_dout[0]),
},
};
int pcm_pin_alt(int pcmfun, int pinnum)
{
if (pcmfun < 0 || pcmfun > 3) {
return -1;
}
const pcm_pin_tables_t *pintable = &pcm_pin_tables[pcmfun];
int i;
for (i = 0; i < pintable->count; i++)
{
if (pintable->pins[i].pinnum == pinnum)
{
return pintable->pins[i].altnum;
}
}
return -1;
}

158
pcm.h

@ -0,0 +1,158 @@
/*
* pcm.h
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
* PCM version Copyright (c) Ton van Overbeek <tvoverbeek @ gmail.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __PCM_H__
#define __PCM_H__
/*
*
* Pin mapping of alternate pin configuration for PCM
*
* GPIO ALT PCM_CLK ALT PCM-FS ALT PCM_DIN ALT PCM_DOUT
*
* 18 0
* 19 0
* 20 0
* 21 0
* 28 2
* 29 2
* 30 2
* 31 2
*
*/
typedef struct
{
uint32_t cs;
#define RPI_PCM_CS_STBY (1 << 25)
#define RPI_PCM_CS_SYNC (1 << 24)
#define RPI_PCM_CS_RXSEX (1 << 23)
#define RPI_PCM_CS_RXF (1 << 22)
#define RPI_PCM_CS_TXE (1 << 21)
#define RPI_PCM_CS_RXD (1 << 20)
#define RPI_PCM_CS_TXD (1 << 19)
#define RPI_PCM_CS_RXR (1 << 18)
#define RPI_PCM_CS_TXW (1 << 17)
#define RPI_PCM_CS_RXERR (1 << 16)
#define RPI_PCM_CS_TXERR (1 << 15)
#define RPI_PCM_CS_RXSYNC (1 << 14)
#define RPI_PCM_CS_TXSYNC (1 << 13)
#define RPI_PCM_CS_DMAEN (1 << 9)
#define RPI_PCM_CS_RXTHR(val) ((val & 0x03) << 7)
#define RPI_PCM_CS_TXTHR(val) ((val & 0x03) << 5)
#define RPI_PCM_CS_RXCLR (1 << 4)
#define RPI_PCM_CS_TXCLR (1 << 3)
#define RPI_PCM_CS_TXON (1 << 2)
#define RPI_PCM_CS_RXON (1 << 1)
#define RPI_PCM_CS_EN (1 << 0)
uint32_t fifo;
uint32_t mode;
#define RPI_PCM_MODE_CLK_DIS (1 << 28)
#define RPI_PCM_MODE_PDMN (1 << 27)
#define RPI_PCM_MODE_PDME (1 << 26)
#define RPI_PCM_MODE_FRXP (1 << 25)
#define RPI_PCM_MODE_FTXP (1 << 24)
#define RPI_PCM_MODE_CLKM (1 << 23)
#define RPI_PCM_MODE_CLKI (1 << 22)
#define RPI_PCM_MODE_FSM (1 << 21)
#define RPI_PCM_MODE_FSI (1 << 20)
#define RPI_PCM_MODE_FLEN(val) ((val & 0x3ff) << 10)
#define RPI_PCM_MODE_FSLEN(val) ((val & 0x3ff) << 0)
uint32_t rxc;
#define RPI_PCM_RXC_CH1WEX (1 << 31)
#define RPI_PCM_RXC_CH1EN (1 << 30)
#define RPI_PCM_RXC_CH1POS(val) ((val & 0x3ff) << 20)
#define RPI_PCM_RXC_CH1WID(val) ((val & 0x0f) << 16)
#define RPI_PCM_RXC_CH2WEX (1 << 15)
#define RPI_PCM_RXC_CH2EN (1 << 14)
#define RPI_PCM_RXC_CH2POS(val) ((val & 0x3ff) << 4)
#define RPI_PCM_RXC_CH2WID(val) ((val & 0x0f) << 0)
uint32_t txc;
#define RPI_PCM_TXC_CH1WEX (1 << 31)
#define RPI_PCM_TXC_CH1EN (1 << 30)
#define RPI_PCM_TXC_CH1POS(val) ((val & 0x3ff) << 20)
#define RPI_PCM_TXC_CH1WID(val) ((val & 0x0f) << 16)
#define RPI_PCM_TXC_CH2WEX (1 << 15)
#define RPI_PCM_TXC_CH2EN (1 << 14)
#define RPI_PCM_TXC_CH2POS(val) ((val & 0x3ff) << 4)
#define RPI_PCM_TXC_CH2WID(val) ((val & 0x0f) << 0)
uint32_t dreq;
#define RPI_PCM_DREQ_TX_PANIC(val) ((val & 0x7f) << 24)
#define RPI_PCM_DREQ_RX_PANIC(val) ((val & 0x7f) << 16)
#define RPI_PCM_DREQ_TX(val) ((val & 0x7f) << 8)
#define RPI_PCM_DREQ_RX(val) ((val & 0x7f) << 0)
uint32_t inten;
#define RPI_PCM_INTEN_RXERR (1 << 3)
#define RPI_PCM_INTEN_TXERR (1 << 2)
#define RPI_PCM_INTEN_RXR (1 << 1)
#define RPI_PCM_INTEN_TXW (1 << 0)
uint32_t intstc;
#define RPI_PCM_INTSTC_RXERR (1 << 3)
#define RPI_PCM_INTSTC_TXERR (1 << 2)
#define RPI_PCM_INTSTC_RXR (1 << 1)
#define RPI_PCM_INTSTC_TXW (1 << 0)
uint32_t gray;
#define RPI_PCM_GRAY_RXFIFOLEVEL(val) ((val & 0x3f) << 16)
#define RPI_PCM_GRAY_FLUSHED(val) ((val & 0x3f) << 10
#define RPI_PCM_GRAY_RXLEVEL(val) ((val & 0x3f) << 4)
#define RPI_PCM_GRAY_FLUSH (1 << 2)
#define RPI_PCM_GRAY_CLR (1 << 1)
#define RPI_PCM_GRAY_EN (1 << 0)
} __attribute__((packed, aligned(4))) pcm_t;
#define PCM_OFFSET (0x00203000)
#define PCM_PERIPH_PHYS (0x7e203000)
#define NUM_PCMFUNS 4
#define PCMFUN_CLK 0
#define PCMFUN_FS 1
#define PCMFUN_DIN 2
#define PCMFUN_DOUT 3
typedef struct
{
int pinnum;
int altnum;
} pcm_pin_table_t;
typedef struct
{
const int count;
const pcm_pin_table_t *pins;
} pcm_pin_tables_t;
int pcm_pin_alt(int pcmfun, int pinnum);
#endif /* __PCM_H__ */

104
pwm.c

@ -0,0 +1,104 @@
/*
* pwm.c
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include "ws2811.h"
#include "pwm.h"
// Mapping of Pin to alternate function for PWM channel 0
const pwm_pin_table_t pwm_pin_chan0[] =
{
{
.pinnum = 12,
.altnum = 0,
},
{
.pinnum = 18,
.altnum = 5,
},
{
.pinnum = 40,
.altnum = 0,
},
};
// Mapping of Pin to alternate function for PWM channel 1
const pwm_pin_table_t pwm_pin_chan1[] =
{
{
.pinnum = 13,
.altnum = 0,
},
{
.pinnum = 19,
.altnum = 5,
},
{
.pinnum = 41,
.altnum = 0,
},
{
.pinnum = 45,
.altnum = 0,
},
};
const pwm_pin_tables_t pwm_pin_tables[RPI_PWM_CHANNELS] =
{
{
.pins = pwm_pin_chan0,
.count = sizeof(pwm_pin_chan0) / sizeof(pwm_pin_chan0[0]),
},
{
.pins = pwm_pin_chan1,
.count = sizeof(pwm_pin_chan1) / sizeof(pwm_pin_chan1[0]),
},
};
int pwm_pin_alt(int chan, int pinnum)
{
const pwm_pin_tables_t *pintable = &pwm_pin_tables[chan];
int i;
for (i = 0; i < pintable->count; i++)
{
if (pintable->pins[i].pinnum == pinnum)
{
return pintable->pins[i].altnum;
}
}
return -1;
}

122
pwm.h

@ -0,0 +1,122 @@
/*
* pwm.h
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __PWM_H__
#define __PWM_H__
/*
*
* Pin mappint of alternate pin configuration for PWM
*
* GPIO ALT PWM0 ALT PWM1
*
* 12 0
* 13 0
* 18 5
* 19 5
* 40 0
* 41 0
* 45 0
* 52 1
* 53 1
*
*/
#define RPI_PWM_CHANNELS 2
typedef struct
{
uint32_t ctl;
#define RPI_PWM_CTL_MSEN2 (1 << 15)
#define RPI_PWM_CTL_USEF2 (1 << 13)
#define RPI_PWM_CTL_POLA2 (1 << 12)
#define RPI_PWM_CTL_SBIT2 (1 << 11)
#define RPI_PWM_CTL_RPTL2 (1 << 10)
#define RPI_PWM_CTL_MODE2 (1 << 9)
#define RPI_PWM_CTL_PWEN2 (1 << 8)
#define RPI_PWM_CTL_MSEN1 (1 << 7)
#define RPI_PWM_CTL_CLRF1 (1 << 6)
#define RPI_PWM_CTL_USEF1 (1 << 5)
#define RPI_PWM_CTL_POLA1 (1 << 4)
#define RPI_PWM_CTL_SBIT1 (1 << 3)
#define RPI_PWM_CTL_RPTL1 (1 << 2)
#define RPI_PWM_CTL_MODE1 (1 << 1)
#define RPI_PWM_CTL_PWEN1 (1 << 0)
uint32_t sta;
#define RPI_PWM_STA_STA4 (1 << 12)
#define RPI_PWM_STA_STA3 (1 << 11)
#define RPI_PWM_STA_STA2 (1 << 10)
#define RPI_PWM_STA_STA1 (1 << 9)
#define RPI_PWM_STA_BERR (1 << 8)
#define RPI_PWM_STA_GAP04 (1 << 7)
#define RPI_PWM_STA_GAP03 (1 << 6)
#define RPI_PWM_STA_GAP02 (1 << 5)
#define RPI_PWM_STA_GAP01 (1 << 4)
#define RPI_PWM_STA_RERR1 (1 << 3)
#define RPI_PWM_STA_WERR1 (1 << 2)
#define RPI_PWM_STA_EMPT1 (1 << 1)
#define RPI_PWM_STA_FULL1 (1 << 0)
uint32_t dmac;
#define RPI_PWM_DMAC_ENAB (1 << 31)
#define RPI_PWM_DMAC_PANIC(val) ((val & 0xff) << 8)
#define RPI_PWM_DMAC_DREQ(val) ((val & 0xff) << 0)
uint32_t resvd_0x0c;
uint32_t rng1;
uint32_t dat1;
uint32_t fif1;
uint32_t resvd_0x1c;
uint32_t rng2;
uint32_t dat2;
} __attribute__((packed, aligned(4))) pwm_t;
#define PWM_OFFSET (0x0020c000)
#define PWM_PERIPH_PHYS (0x7e20c000)
typedef struct
{
int pinnum;
int altnum;
} pwm_pin_table_t;
typedef struct
{
const int count;
const pwm_pin_table_t *pins;
} pwm_pin_tables_t;
int pwm_pin_alt(int chan, int pinnum);
#endif /* __PWM_H__ */

9
python/.gitignore vendored

@ -0,0 +1,9 @@
*.pyc
*.so
build/
*.egg-info/
rpi_ws281x.py
rpi_ws281x_wrap.c
_rpi_ws281x.py
*.egg
*.zip

@ -0,0 +1,49 @@
## Deprecated
This Python code is being phased out and replaced with https://github.com/rpi-ws281x/rpi-ws281x-python
If you're just looking to install the Python library, you can: `sudo pip install rpi_ws281x` or `sudo pip3 install rpi_ws281x` depending on your Python version of choice or find releases here: https://github.com/rpi-ws281x/rpi-ws281x-python/releases
For issues and bugs with (or contributions to) the Python library, please see: https://github.com/rpi-ws281x/rpi-ws281x-python/issues
----
## Build
As this is just a python wrapper for the library you must first follow
the build instructions in the parent directory.
When complete, you can build this python wrapper:
```
sudo apt-get install python-dev swig
python ./setup.py build
```
If you are rebuilding after fetching some updated commits, you might need to
remove the build directory first
```
rm -rf ./build
```
## Install
If you want to install the library (in a virtualenv or in the system), so that you can `import neopixel` from anywhere, you need to run:
```
python ./setup.py install
```
Depending on where you are installing, root privileges may be needed (prepend `sudo` to the install command).
## Run a demo
```
sudo PYTHONPATH=".:build/lib.linux-armv7l-2.7" python examples/strandtest.py
```
If you installed the library, there is no need to specify `PYTHONPATH`:
```
sudo python examples/strandtest.py
```

@ -0,0 +1,75 @@
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example. Showcases
# various animations on a strip of NeoPixels.
import time
from neopixel import *
# LED strip configuration:
LED_COUNT = 494 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0
LED_STRIP = ws.SK6812_STRIP_RGBW
#LED_STRIP = ws.SK6812W_STRIP
class Led:
leds = []
def __init__(self, id, x, y):
self.x = x
self.y = y
Led.leds.append(self)
def colorFromIntensity(intensity):
#intensity should be 0-255
if intensity>20:
return Color(0,int(intensity),int(intensity/2),int(intensity/8)+20)
else:
return Color(0,0,0,20)
def intensityFromDistance(distance):
if distance<0:
return 0
intensity = 255-(distance/3)
if intensity < 0:
return 0
else:
return intensity
# Main program logic follows:
if __name__ == '__main__':
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
# Intialize the library (must be called once before other functions).
strip.begin()
print ('Press Ctrl-C to quit.')
with open("leds.txt", "r") as infile:
for line in infile:
entry = [int(x) for x in line.split(',')]
Led(entry[0], entry[1], entry[2])
# all LEDs now ready
edge = -500
t = 0
while True:
t+=1
for i, led in enumerate(Led.leds):
if t % 2 ==0:
strip.setPixelColor(i, Color(0b10101010,
0b10101010,
0b10101010,
0b10101010))
else:
strip.setPixelColor(i, Color(0,0,0,0))
strip.show()
time.sleep(1)

@ -0,0 +1,221 @@
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example. Showcases
# various animations on a strip of NeoPixels.
import time
import random
from neopixel import *
# LED strip configuration:
LED_COUNT = 494 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0
LED_STRIP = ws.SK6812_STRIP_RGBW
#LED_STRIP = ws.SK6812W_STRIP
class Led:
leds = []
def __init__(self, id, x, y):
self.x = x
self.y = y
Led.leds.append(self)
class Star:
stars = []
def __init__(self):
self.starstate = 0
self.starBrightness = 0
self.starCountdown = 0
self.starLED = 50
Star.stars.append(self)
def update(self, strip):
if self.starstate == 0:
self.starBrightness += 3
if self.starBrightness > 120:
self.starstate = 1
if self.starstate == 1:
self.starBrightness -= self.starBrightness/100.0
if self.starBrightness < 5:
self.starstate = 2
self.starBrightness = 0
self.starCountdown = random.randint(100, 500)
if self.starstate == 2:
self.starCountdown -= 1
if self.starCountdown == 0:
self.starLED = 0
otherStars = [s.starLED for s in Star.stars]
goodPlace = False
while not goodPlace:
self.starLED = random.randint(0,493)
goodPlace = True
if self.starLED in range(236, 349):
goodPlace = False
if Led.leds[self.starLED].y < random.random():
goodPlace = False
for otherStar in otherStars:
if abs(self.starLED-otherStar)<4:
goodPlace = False
self.starstate = 0
brightness = int(self.starBrightness + (self.starBrightness * random.random())/20.0)
strip.setPixelColor(self.starLED, Color(0,0,int(brightness/2),brightness))
def wheel(pos):
"""Generate rainbow colors across 0-255 positions."""
if pos < 85:
return Color(pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return Color(255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return Color(0, pos * 3, 255 - pos * 3)
def colorFromIntensity(intensity):
#intensity should be 0-255
if intensity>20:
return Color(0,intensity,intensity/2,intensity/8+20)
else:
return Color(0,0,0,20)
def intensityFromDistance(distance):
if distance<0:
return 0
intensity = 255-(distance/3)
if intensity < 0:
return 0
else:
return intensity
def turnOnChain(chain):
for light in chain:
strip.setPixelColor(light, Color(0,255,0,0))
strip.setPixelColor(light+1, Color(0,255,0,0))
strip.setPixelColor(light+2, Color(0,0,0,0))
strip.setPixelColor(light-1, Color(0,0,0,0))
# Main program logic follows:
if __name__ == '__main__':
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
# Intialize the library (must be called once before other functions).
strip.begin()
print ('Press Ctrl-C to quit.')
with open("leds.txt", "r") as infile:
for line in infile:
entry = [int(x) for x in line.split(',')]
Led(entry[0], entry[1], entry[2])
limits = [ min([l.x for l in Led.leds]), max([l.x for l in Led.leds]), min([l.y for l in Led.leds]), max([l.y for l in Led.leds])]
for l in Led.leds:
l.y = ( float(l.y - float(limits[3])) / (limits[2]-limits[3]) )
l.x = ( float(l.x - float(limits[0])) / (limits[3]-limits[2]) )
x_max = max([l.x for l in Led.leds])
print ("Maximum X: {}".format(x_max))
# all LEDs now ready
edge = -500
counter = 1
hider = 0
animation = 0
stars = []
for i in range(0, 10):
Star()
while True:
for i, led in enumerate(Led.leds):
# intensity = intensityFromDistance(edge-(led.x - led.y/3))
# strip.setPixelColor(i, colorFromIntensity(intensity))
# blueness = int(i/2)%25
if(i > 236 and i<349):
# Gör bokstaven A grön
strip.setPixelColor(i, Color(70,13,0,5))
else:
blueness = int((1.0-led.y)**3 * 60) if led.y>0.10 else 0
if blueness < 5:
blueness = 5
#redness = int((led.x / x_max)**2 * 255)
redness = int((1.0-led.y)**8 * 4)
strip.setPixelColor(i, Color(0,redness,blueness,0))
# strip.setPixelColor(440, Color(random.randint(68,72),random.randint(68,72),random.randint(68,72),random.randint(4,6)))
# lights = [257, 334, 283, 249, 290, 346, 299, 311, 242]
# for light in lights:
# strip.setPixelColor(light, Color(0,255,0,0))
# strip.setPixelColor(light+1, Color(0,255,0,0))
# strip.setPixelColor(light+2, Color(0,0,0,0))
# strip.setPixelColor(light-1, Color(0,0,0,0))
chain0 = [260, 274]
chain1 = [254, 334, 283]
chain2 = [247, 290, 346]
chain3 = [299, 314, 241]
strip.setPixelColor(264, Color(0,0,0,50))
strip.setPixelColor(265, Color(160,255,0, 20))
strip.setPixelColor(266, Color(160,255,0, 20))
strip.setPixelColor(267, Color(160,255,0, 20))
strip.setPixelColor(268, Color(0,0,0,50))
animation+=1
animation %= 400
if animation>= 0 and animation <50:
turnOnChain(chain0)
turnOnChain(chain2)
if animation >=50 and animation <100:
turnOnChain(chain1)
turnOnChain(chain2)
if animation >=100 and animation <150:
turnOnChain(chain1)
turnOnChain(chain3)
if animation >=150 and animation <200:
turnOnChain(chain2)
turnOnChain(chain3)
if animation >=200 and animation <250:
turnOnChain(chain0)
turnOnChain(chain2)
if animation >=250 and animation <300:
turnOnChain(chain0)
turnOnChain(chain3)
if animation >=300 and animation <350:
turnOnChain(chain1)
turnOnChain(chain3)
if animation >=350 and animation <400:
turnOnChain(chain1)
turnOnChain(chain0)
for star in Star.stars:
star.update(strip)
#time.sleep(0.05)
counter +=1
strip.show()
# edge+=10
# if edge>5000:
# edge = -500
# time.sleep(0.01)

@ -0,0 +1,160 @@
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example. Showcases
# various animations on a strip of NeoPixels.
import random
from neopixel import ws, Adafruit_NeoPixel, Color
# LED strip configuration:
LED_COUNT = 494 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 1200000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # Invert when using NPN transistor level shift
LED_CHANNEL = 0
LED_STRIP = ws.SK6812_STRIP_RGBW
class Led:
leds = []
def __init__(self, id, x, y):
self.x = x
self.y = y
Led.leds.append(self)
class Star:
stars = []
def __init__(self):
self.starstate = 0
self.starBrightness = 0
self.starCountdown = 0
self.starLED = 50
Star.stars.append(self)
def update(self, strip):
if self.starstate == 0:
self.starBrightness += 3
if self.starBrightness > 120:
self.starstate = 1
if self.starstate == 1:
self.starBrightness -= self.starBrightness/100.0
if self.starBrightness < 5:
self.starstate = 2
self.starBrightness = 0
self.starCountdown = random.randint(100, 500)
if self.starstate == 2:
self.starCountdown -= 1
if self.starCountdown == 0:
self.starLED = 0
otherStars = [s.starLED for s in Star.stars]
goodPlace = False
while not goodPlace:
self.starLED = random.randint(0, 493)
goodPlace = True
if Led.leds[self.starLED].y < random.random():
goodPlace = False
for otherStar in otherStars:
if abs(self.starLED-otherStar) < 4:
goodPlace = False
self.starstate = 0
brightness = int(self.starBrightness + (self.starBrightness * random.random())/20.0)
strip.setPixelColor(self.starLED, Color(0, 0, int(brightness/2), brightness))
def wheel(pos):
"""Generate rainbow colors across 0-255 positions."""
if pos < 85:
return Color(pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return Color(255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return Color(0, pos * 3, 255 - pos * 3)
def colorFromIntensity(intensity):
# Intensity should be 0-255
if intensity > 20:
return Color(0, intensity, intensity/2, intensity/8+20)
else:
return Color(0, 0, 0, 20)
def intensityFromDistance(distance):
if distance < 0:
return 0
intensity = 255-(distance/3)
if intensity < 0:
return 0
else:
return intensity
def turnOnChain(chain):
for light in chain:
strip.setPixelColor(light, Color(0, 255, 0, 0))
strip.setPixelColor(light+1, Color(0, 255, 0, 0))
strip.setPixelColor(light+2, Color(0, 0, 0, 0))
strip.setPixelColor(light-1, Color(0, 0, 0, 0))
# Main program logic follows:
if __name__ == '__main__':
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA,
LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL,
LED_STRIP)
# Intialize the library (must be called once before other functions).
strip.begin()
print('Press Ctrl-C to quit.')
with open("leds.txt", "r") as infile:
for line in infile:
entry = [int(x) for x in line.split(',')]
Led(entry[0], entry[1], entry[2])
limits = [min([l.x for l in Led.leds]),
max([l.x for l in Led.leds]),
min([l.y for l in Led.leds]),
max([l.y for l in Led.leds])]
for l in Led.leds:
l.y = (float(l.y - float(limits[3])) / (limits[2]-limits[3]))
l.x = (float(l.x - float(limits[0])) / (limits[3]-limits[2]))
x_max = max([l.x for l in Led.leds])
print("Maximum X: {}".format(x_max))
# all LEDs now ready
edge = -500
counter = 1
hider = 0
animation = 0
stars = []
for i in range(0, 10):
Star()
while True:
for i, led in enumerate(Led.leds):
blueness = int((1.0-led.y)**3 * 60) if led.y > 0.10 else 0
if blueness < 5:
blueness = 5
redness = int((1.0-led.y)**8 * 4)
strip.setPixelColor(i, Color(0, redness, blueness, 0))
for star in Star.stars:
star.update(strip)
counter += 1
strip.show()

@ -0,0 +1,160 @@
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example. Showcases
# various animations on a strip of NeoPixels.
import random
from neopixel import ws, Adafruit_NeoPixel, Color
# LED strip configuration:
LED_COUNT = 494 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # Invert when using NPN transistor level shift
LED_CHANNEL = 0
LED_STRIP = ws.SK6812_STRIP_RGBW
class Led:
leds = []
def __init__(self, id, x, y):
self.x = x
self.y = y
Led.leds.append(self)
class Star:
stars = []
def __init__(self):
self.starstate = 0
self.starBrightness = 0
self.starCountdown = 0
self.starLED = 50
Star.stars.append(self)
def update(self, strip):
if self.starstate == 0:
self.starBrightness += 3
if self.starBrightness > 120:
self.starstate = 1
if self.starstate == 1:
self.starBrightness -= self.starBrightness/100.0
if self.starBrightness < 5:
self.starstate = 2
self.starBrightness = 0
self.starCountdown = random.randint(100, 500)
if self.starstate == 2:
self.starCountdown -= 1
if self.starCountdown == 0:
self.starLED = 0
otherStars = [s.starLED for s in Star.stars]
goodPlace = False
while not goodPlace:
self.starLED = random.randint(0, 493)
goodPlace = True
if Led.leds[self.starLED].y < random.random():
goodPlace = False
for otherStar in otherStars:
if abs(self.starLED-otherStar) < 4:
goodPlace = False
self.starstate = 0
brightness = int(self.starBrightness + (self.starBrightness * random.random())/20.0)
strip.setPixelColor(self.starLED, Color(0, 0, int(brightness/2), brightness))
def wheel(pos):
"""Generate rainbow colors across 0-255 positions."""
if pos < 85:
return Color(pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return Color(255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return Color(0, pos * 3, 255 - pos * 3)
def colorFromIntensity(intensity):
# Intensity should be 0-255
if intensity > 20:
return Color(0, intensity, intensity/2, intensity/8+20)
else:
return Color(0, 0, 0, 20)
def intensityFromDistance(distance):
if distance < 0:
return 0
intensity = 255-(distance/3)
if intensity < 0:
return 0
else:
return intensity
def turnOnChain(chain):
for light in chain:
strip.setPixelColor(light, Color(0, 255, 0, 0))
strip.setPixelColor(light+1, Color(0, 255, 0, 0))
strip.setPixelColor(light+2, Color(0, 0, 0, 0))
strip.setPixelColor(light-1, Color(0, 0, 0, 0))
# Main program logic follows:
if __name__ == '__main__':
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA,
LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL,
LED_STRIP)
# Intialize the library (must be called once before other functions).
strip.begin()
print('Press Ctrl-C to quit.')
with open("leds.txt", "r") as infile:
for line in infile:
entry = [int(x) for x in line.split(',')]
Led(entry[0], entry[1], entry[2])
limits = [min([l.x for l in Led.leds]),
max([l.x for l in Led.leds]),
min([l.y for l in Led.leds]),
max([l.y for l in Led.leds])]
for l in Led.leds:
l.y = (float(l.y - float(limits[3])) / (limits[2]-limits[3]))
l.x = (float(l.x - float(limits[0])) / (limits[3]-limits[2]))
x_max = max([l.x for l in Led.leds])
print("Maximum X: {}".format(x_max))
# all LEDs now ready
edge = -500
counter = 1
hider = 0
animation = 0
stars = []
for i in range(0, 10):
Star()
while True:
for i, led in enumerate(Led.leds):
blueness = int((1.0-led.y)**3 * 60) if led.y > 0.10 else 0
if blueness < 5:
blueness = 5
redness = int((1.0-led.y)**8 * 4)
strip.setPixelColor(i, Color(0, redness, blueness, 0))
for star in Star.stars:
star.update(strip)
counter += 1
strip.show()

@ -0,0 +1,3 @@
#!/usr/bin/env bash
sudo PYTHONPATH=".:build/lib.linux-armv7l-2.7" python3 animate.py

@ -0,0 +1,82 @@
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example. Showcases
# various animations on a strip of NeoPixels.
import time
from neopixel import *
# LED strip configuration:
LED_COUNT = 494 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0
LED_STRIP = ws.SK6812_STRIP_RGBW
#LED_STRIP = ws.SK6812W_STRIP
class Led:
leds = []
def __init__(self, id, x, y):
self.x = x
self.y = y
Led.leds.append(self)
def wheel(pos):
"""Generate rainbow colors across 0-255 positions."""
if pos < 85:
return Color(pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return Color(255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return Color(0, pos * 3, 255 - pos * 3)
def colorFromIntensity(intensity):
#intensity should be 0-255
if intensity>20:
return Color(int(intensity/2),int(intensity/2),int(intensity/2),max(int(intensity),20))
else:
return Color(0,0,0,20)
def intensityFromDistance(distance):
if distance<0:
return 0
intensity = 255-(distance/3)
if intensity < 0:
return 0
else:
return intensity
# Main program logic follows:
if __name__ == '__main__':
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
# Intialize the library (must be called once before other functions).
strip.begin()
print ('Press Ctrl-C to quit.')
with open("leds.txt", "r") as infile:
for line in infile:
entry = [int(x) for x in line.split(',')]
Led(entry[0], entry[1], entry[2])
# all LEDs now ready
edge = -500
while True:
# counter = 0
for i, led in enumerate(Led.leds):
intensity = intensityFromDistance(edge-(led.x - led.y/3))
strip.setPixelColor(i, colorFromIntensity(intensity))
strip.show()
edge+=10
if edge>5000:
edge = -500
# time.sleep(0.01)

@ -0,0 +1 @@
aniamte_starrynight.py

@ -0,0 +1,104 @@
# Example of low-level Python wrapper for rpi_ws281x library.
# Author: Tony DiCola (tony@tonydicola.com), Jeremy Garff (jer@jers.net)
#
# This is an example of how to use the SWIG-generated _rpi_ws281x module.
# You probably don't want to use this unless you are building your own library,
# because the SWIG generated module is clunky and verbose. Instead look at the
# high level Python port of Adafruit's NeoPixel Arduino library in strandtest.py.
#
# This code will animate a number of WS281x LEDs displaying rainbow colors.
import time
import _rpi_ws281x as ws
# LED configuration.
LED_CHANNEL = 0
LED_COUNT = 16 # How many LEDs to light.
LED_FREQ_HZ = 800000 # Frequency of the LED signal. Should be 800khz or 400khz.
LED_DMA_NUM = 10 # DMA channel to use, can be 0-14.
LED_GPIO = 18 # GPIO connected to the LED signal line. Must support PWM!
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = 0 # Set to 1 to invert the LED signal, good if using NPN
# transistor as a 3.3V->5V level converter. Keep at 0
# for a normal/non-inverted signal.
#LED_STRIP = ws.WS2811_STRIP_RGB
#LED_STRIP = ws.WS2811_STRIP_GBR
#LED_STRIP = ws.SK6812_STRIP_RGBW
LED_STRIP = ws.SK6812W_STRIP
# Define colors which will be used by the example. Each color is an unsigned
# 32-bit value where the lower 24 bits define the red, green, blue data (each
# being 8 bits long).
DOT_COLORS = [ 0x200000, # red
0x201000, # orange
0x202000, # yellow
0x002000, # green
0x002020, # lightblue
0x000020, # blue
0x100010, # purple
0x200010 ] # pink
# Create a ws2811_t structure from the LED configuration.
# Note that this structure will be created on the heap so you need to be careful
# that you delete its memory by calling delete_ws2811_t when it's not needed.
leds = ws.new_ws2811_t()
# Initialize all channels to off
for channum in range(2):
channel = ws.ws2811_channel_get(leds, channum)
ws.ws2811_channel_t_count_set(channel, 0)
ws.ws2811_channel_t_gpionum_set(channel, 0)
ws.ws2811_channel_t_invert_set(channel, 0)
ws.ws2811_channel_t_brightness_set(channel, 0)
channel = ws.ws2811_channel_get(leds, LED_CHANNEL)
ws.ws2811_channel_t_count_set(channel, LED_COUNT)
ws.ws2811_channel_t_gpionum_set(channel, LED_GPIO)
ws.ws2811_channel_t_invert_set(channel, LED_INVERT)
ws.ws2811_channel_t_brightness_set(channel, LED_BRIGHTNESS)
ws.ws2811_channel_t_strip_type_set(channel, LED_STRIP)
ws.ws2811_t_freq_set(leds, LED_FREQ_HZ)
ws.ws2811_t_dmanum_set(leds, LED_DMA_NUM)
# Initialize library with LED configuration.
resp = ws.ws2811_init(leds)
if resp != ws.WS2811_SUCCESS:
message = ws.ws2811_get_return_t_str(resp)
raise RuntimeError('ws2811_init failed with code {0} ({1})'.format(resp, message))
# Wrap following code in a try/finally to ensure cleanup functions are called
# after library is initialized.
try:
offset = 0
while True:
# Update each LED color in the buffer.
for i in range(LED_COUNT):
# Pick a color based on LED position and an offset for animation.
color = DOT_COLORS[(i + offset) % len(DOT_COLORS)]
# Set the LED color buffer value.
ws.ws2811_led_set(channel, i, color)
# Send the LED color data to the hardware.
resp = ws.ws2811_render(leds)
if resp != ws.WS2811_SUCCESS:
message = ws.ws2811_get_return_t_str(resp)
raise RuntimeError('ws2811_render failed with code {0} ({1})'.format(resp, message))
# Delay for a small period of time.
time.sleep(0.25)
# Increase offset to animate colors moving. Will eventually overflow, which
# is fine.
offset += 1
finally:
# Ensure ws2811_fini is called before the program quits.
ws.ws2811_fini(leds)
# Example of calling delete function to clean up structure memory. Isn't
# strictly necessary at the end of the program execution here, but is good practice.
ws.delete_ws2811_t(leds)

@ -0,0 +1,107 @@
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example. Showcases
# various animations on a strip of NeoPixels.
import time
from neopixel import *
# LED strip configuration:
LED_COUNT = 494 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0
LED_STRIP = ws.SK6812_STRIP_RGBW
#LED_STRIP = ws.SK6812W_STRIP
# Define functions which animate LEDs in various ways.
def colorWipe(strip, color, wait_ms=15):
"""Wipe color across display a pixel at a time."""
for i in range(strip.numPixels()):
strip.setPixelColor(i, color)
strip.show()
time.sleep(wait_ms/1000.0)
def theaterChase(strip, color, wait_ms=15, iterations=10):
"""Movie theater light style chaser animation."""
for j in range(iterations):
for q in range(3):
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, color)
strip.show()
time.sleep(wait_ms/1000.0)
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, 0)
def wheel(pos):
"""Generate rainbow colors across 0-255 positions."""
if pos < 85:
return Color(pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return Color(255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return Color(0, pos * 3, 255 - pos * 3)
def rainbow(strip, wait_ms=15, iterations=1):
"""Draw rainbow that fades across all pixels at once."""
for j in range(256*iterations):
for i in range(strip.numPixels()):
strip.setPixelColor(i, wheel((i+j) & 255))
strip.show()
time.sleep(wait_ms/1000.0)
def rainbowCycle(strip, wait_ms=15, iterations=5):
"""Draw rainbow that uniformly distributes itself across all pixels."""
for j in range(256*iterations):
for i in range(strip.numPixels()):
strip.setPixelColor(i, wheel(((i * 256 // strip.numPixels()) + j) & 255))
strip.show()
time.sleep(wait_ms/1000.0)
def theaterChaseRainbow(strip, wait_ms=15):
"""Rainbow movie theater light style chaser animation."""
for j in range(256):
for q in range(3):
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, wheel((i+j) % 255))
strip.show()
time.sleep(wait_ms/1000.0)
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, 0)
# Main program logic follows:
if __name__ == '__main__':
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
# Intialize the library (must be called once before other functions).
strip.begin()
print ('Press Ctrl-C to quit.')
while True:
# Color wipe animations.
colorWipe(strip, Color(255, 0, 0)) # Red wipe
colorWipe(strip, Color(0, 255, 0)) # Blue wipe
colorWipe(strip, Color(0, 0, 255)) # Green wipe
colorWipe(strip, Color(0, 0, 0, 255)) # White wipe
colorWipe(strip, Color(255, 255, 255)) # Composite White wipe
colorWipe(strip, Color(255, 255, 255, 255)) # Composite White + White LED wipe
# Theater chase animations.
theaterChase(strip, Color(127, 0, 0)) # Red theater chase
theaterChase(strip, Color(0, 127, 0)) # Green theater chase
theaterChase(strip, Color(0, 0, 127)) # Blue theater chase
theaterChase(strip, Color(0, 0, 0, 127)) # White theater chase
theaterChase(strip, Color(127, 127, 127, 0)) # Composite White theater chase
theaterChase(strip, Color(127, 127, 127, 127)) # Composite White + White theater chase
# Rainbow animations.
rainbow(strip)
rainbowCycle(strip)
theaterChaseRainbow(strip)

@ -0,0 +1,52 @@
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example. Showcases
# various animations on a strip of NeoPixels.
import time
from neopixel import *
# LED strip configuration:
LED_COUNT = 30 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0
#LED_STRIP = ws.SK6812_STRIP_RGBW
LED_STRIP = ws.SK6812W_STRIP
# Define functions which animate LEDs in various ways.
def colorWipe(strip, color, wait_ms=50):
"""Wipe color across display a pixel at a time."""
for i in range(strip.numPixels()):
strip.setPixelColor(i, color)
strip.show()
time.sleep(wait_ms/1000.0)
# Main program logic follows:
if __name__ == '__main__':
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_STRIP)
# Intialize the library (must be called once before other functions).
strip.begin()
print ('Press Ctrl-C to quit.')
while True:
# Color wipe animations.
colorWipe(strip, Color(255, 0, 0), 0) # Red wipe
time.sleep(2)
colorWipe(strip, Color(0, 255, 0), 0) # Blue wipe
time.sleep(2)
colorWipe(strip, Color(0, 0, 255), 0) # Green wipe
time.sleep(2)
colorWipe(strip, Color(0, 0, 0, 255), 0) # White wipe
time.sleep(2)
colorWipe(strip, Color(255, 255, 255), 0) # Composite White wipe
time.sleep(2)
colorWipe(strip, Color(255, 255, 255, 255), 0) # Composite White + White LED wipe
time.sleep(2)

@ -0,0 +1,126 @@
#!/usr/bin/env python3
# NeoPixel library light-painting example
# Author: Gary Servin (garyservin@gmail.com)
#
# Lightpainting example for displaying images one column at a time and capturing
# it by taking a long exposure photograph.
# Based on https://github.com/scottjgibson/PixelPi
import time
from neopixel import *
import argparse
# Button
import RPi.GPIO as GPIO
# Lightpainting
from PIL import Image
# LED strip configuration:
LED_COUNT = 128 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (18 uses PWM!).
#LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
BUTTON_CHANNEL = 19 # GPIO pin connected to the start button
def UnColor(color):
return ((color >> 24) & 0xFF , (color >> 16) & 0xFF, (color >> 8) & 0xFF, color & 0xFF)
def lightpaint(filename, frame_rate=100, column_rate=1, reverse_x=False, reverse_y=False, loop=False):
img = Image.open(filename).convert("RGB")
# Check that the height of the image is greater than or equal the number of LEDs on the strip
if(img.size[1] < LED_COUNT):
raise Exception("Image height is smaller than led strip size. Required height = {}".format(LED_COUNT))
elif(img.size[1] > LED_COUNT):
print "Resizing image"
new_width = LED_COUNT * img.size[0] / img.size[1]
img = img.resize((new_width, LED_COUNT), Image.ANTIALIAS)
input_image = img.load()
image_width = img.size[0]
column = [0 for x in range(image_width)]
for x in range(image_width):
column[x] = [None] * (LED_COUNT)
for x in range(image_width):
for y in range(LED_COUNT):
value = input_image[x, y]
column[x][y] = Color(value[1], value[0], value[2])
while True:
# Wait for button to be pressed before displaying image
if not loop:
print("Waiting for button to be pressed")
GPIO.wait_for_edge(BUTTON_CHANNEL, GPIO.FALLING)
time.sleep(0.5)
x_range = range(image_width)
if reverse_x:
x_range.reverse()
y_range = range(LED_COUNT)
if reverse_y:
y_range.reverse()
for x in x_range:
led_pos = 0
for y in y_range:
strip.setPixelColor(led_pos, column[x][y])
led_pos += 1
strip.show()
time.sleep(column_rate / 1000.0)
# Wait for `frame_rate` ms before drawing a new frame
time.sleep(frame_rate / 1000.0)
# Define functions which animate LEDs in various ways.
def colorWipe(strip, color, wait_ms=50):
"""Wipe color across display a pixel at a time."""
for i in range(strip.numPixels()):
strip.setPixelColor(i, color)
strip.show()
time.sleep(wait_ms/1000.0)
# Main program logic follows:
if __name__ == '__main__':
# Process arguments
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--clear', action='store_true', help='clear the display on exit')
parser.add_argument('-f', '--file', action='store', help='Filename to display')
parser.add_argument('-r', '--frame_rate', action='store', default=100, help='Rate between each frame. Defines how fast a new frame is displayed')
parser.add_argument('-l', '--column_rate', action='store', default=1, help='Rate between each column. Defines how fast or slow you need to move the stick')
parser.add_argument('-b', '--brightness', action='store', default=10, help='Brightness of the LED. Set to 0 for darkest and 255 for brightest')
parser.add_argument('-x', '--reverse_x', action='store_true', help='Reverse the image in the X direction')
parser.add_argument('-y', '--reverse_y', action='store_true', help='Reverse the image in the Y direction')
parser.add_argument('--loop', action='store_true', help='Play frames in a loop')
args = parser.parse_args()
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, args.brightness, LED_CHANNEL)
# Intialize the library (must be called once before other functions).
strip.begin()
# Button
GPIO.setmode(GPIO.BOARD)
GPIO.setup(BUTTON_CHANNEL, GPIO.IN, pull_up_down=GPIO.PUD_UP)
print ('Press Ctrl-C to quit.')
if not args.clear:
print('Use "-c" argument to clear LEDs on exit')
try:
while True:
print ('Lightpaint.')
lightpaint(args.file, float(args.frame_rate), float(args.column_rate), args.reverse_x, args.reverse_y, args.loop)
except KeyboardInterrupt:
if args.clear:
colorWipe(strip, Color(0,0,0), 10)
GPIO.cleanup()

@ -0,0 +1,98 @@
# Example of low-level Python wrapper for rpi_ws281x library.
# Author: Tony DiCola (tony@tonydicola.com), Jeremy Garff (jer@jers.net)
#
# This is an example of how to use the SWIG-generated _rpi_ws281x module.
# You probably don't want to use this unless you are building your own library,
# because the SWIG generated module is clunky and verbose. Instead look at the
# high level Python port of Adafruit's NeoPixel Arduino library in strandtest.py.
#
# This code will animate a number of WS281x LEDs displaying rainbow colors.
import time
import _rpi_ws281x as ws
# LED configuration.
LED_CHANNEL = 0
LED_COUNT = 16 # How many LEDs to light.
LED_FREQ_HZ = 800000 # Frequency of the LED signal. Should be 800khz or 400khz.
LED_DMA_NUM = 10 # DMA channel to use, can be 0-14.
LED_GPIO = 18 # GPIO connected to the LED signal line. Must support PWM!
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = 0 # Set to 1 to invert the LED signal, good if using NPN
# transistor as a 3.3V->5V level converter. Keep at 0
# for a normal/non-inverted signal.
# Define colors which will be used by the example. Each color is an unsigned
# 32-bit value where the lower 24 bits define the red, green, blue data (each
# being 8 bits long).
DOT_COLORS = [ 0x200000, # red
0x201000, # orange
0x202000, # yellow
0x002000, # green
0x002020, # lightblue
0x000020, # blue
0x100010, # purple
0x200010 ] # pink
# Create a ws2811_t structure from the LED configuration.
# Note that this structure will be created on the heap so you need to be careful
# that you delete its memory by calling delete_ws2811_t when it's not needed.
leds = ws.new_ws2811_t()
# Initialize all channels to off
for channum in range(2):
channel = ws.ws2811_channel_get(leds, channum)
ws.ws2811_channel_t_count_set(channel, 0)
ws.ws2811_channel_t_gpionum_set(channel, 0)
ws.ws2811_channel_t_invert_set(channel, 0)
ws.ws2811_channel_t_brightness_set(channel, 0)
channel = ws.ws2811_channel_get(leds, LED_CHANNEL)
ws.ws2811_channel_t_count_set(channel, LED_COUNT)
ws.ws2811_channel_t_gpionum_set(channel, LED_GPIO)
ws.ws2811_channel_t_invert_set(channel, LED_INVERT)
ws.ws2811_channel_t_brightness_set(channel, LED_BRIGHTNESS)
ws.ws2811_t_freq_set(leds, LED_FREQ_HZ)
ws.ws2811_t_dmanum_set(leds, LED_DMA_NUM)
# Initialize library with LED configuration.
resp = ws.ws2811_init(leds)
if resp != ws.WS2811_SUCCESS:
message = ws.ws2811_get_return_t_str(resp)
raise RuntimeError('ws2811_init failed with code {0} ({1})'.format(resp, message))
# Wrap following code in a try/finally to ensure cleanup functions are called
# after library is initialized.
try:
offset = 0
while True:
# Update each LED color in the buffer.
for i in range(LED_COUNT):
# Pick a color based on LED position and an offset for animation.
color = DOT_COLORS[(i + offset) % len(DOT_COLORS)]
# Set the LED color buffer value.
ws.ws2811_led_set(channel, i, color)
# Send the LED color data to the hardware.
resp = ws.ws2811_render(leds)
if resp != ws.WS2811_SUCCESS:
message = ws.ws2811_get_return_t_str(resp)
raise RuntimeError('ws2811_render failed with code {0} ({1})'.format(resp, message))
# Delay for a small period of time.
time.sleep(0.25)
# Increase offset to animate colors moving. Will eventually overflow, which
# is fine.
offset += 1
finally:
# Ensure ws2811_fini is called before the program quits.
ws.ws2811_fini(leds)
# Example of calling delete function to clean up structure memory. Isn't
# strictly necessary at the end of the program execution here, but is good practice.
ws.delete_ws2811_t(leds)

@ -0,0 +1,78 @@
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example. Showcases
# various animations on a strip of NeoPixels.
import time
from neopixel import *
# LED strip configuration:
LED_1_COUNT = 30 # Number of LED pixels.
LED_1_PIN = 18 # GPIO pin connected to the pixels (must support PWM! GPIO 13 and 18 on RPi 3).
LED_1_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_1_DMA = 10 # DMA channel to use for generating signal (Between 1 and 14)
LED_1_BRIGHTNESS = 128 # Set to 0 for darkest and 255 for brightest
LED_1_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_1_CHANNEL = 0 # 0 or 1
LED_1_STRIP = ws.SK6812_STRIP_GRBW
LED_2_COUNT = 15 # Number of LED pixels.
LED_2_PIN = 13 # GPIO pin connected to the pixels (must support PWM! GPIO 13 or 18 on RPi 3).
LED_2_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_2_DMA = 11 # DMA channel to use for generating signal (Between 1 and 14)
LED_2_BRIGHTNESS = 128 # Set to 0 for darkest and 255 for brightest
LED_2_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_2_CHANNEL = 1 # 0 or 1
LED_2_STRIP = ws.WS2811_STRIP_GRB
def multiColorWipe(color1, color2, wait_ms=5):
global strip1
global strip2
"""Wipe color across multiple LED strips a pixel at a time."""
for i in range(strip1.numPixels()):
if i % 2:
# even number
strip1.setPixelColor(i, color1)
strip2.setPixelColor(i / 2, color2)
strip1.show()
time.sleep(wait_ms/1000.0)
strip2.show()
time.sleep(wait_ms/1000.0)
else:
# odd number
strip1.setPixelColor(i, color1)
strip1.show()
time.sleep(wait_ms/1000.0)
time.sleep(1)
def blackout(strip):
for i in range(max(strip1.numPixels(), strip1.numPixels())):
strip.setPixelColor(i, Color(0,0,0))
strip.show()
# Main program logic follows:
if __name__ == '__main__':
# Create NeoPixel objects with appropriate configuration for each strip.
strip1 = Adafruit_NeoPixel(LED_1_COUNT, LED_1_PIN, LED_1_FREQ_HZ, LED_1_DMA, LED_1_INVERT, LED_1_BRIGHTNESS, LED_1_CHANNEL, LED_1_STRIP)
strip2 = Adafruit_NeoPixel(LED_2_COUNT, LED_2_PIN, LED_2_FREQ_HZ, LED_2_DMA, LED_2_INVERT, LED_2_BRIGHTNESS, LED_2_CHANNEL, LED_2_STRIP)
# Intialize the library (must be called once before other functions).
strip1.begin()
strip2.begin()
print ('Press Ctrl-C to quit.')
# Black out any LEDs that may be still on for the last run
blackout(strip1)
blackout(strip2)
while True:
# Multi Color wipe animations.
multiColorWipe(Color(255, 0, 0), Color(255, 0, 0)) # Red wipe
multiColorWipe(Color(0, 255, 0), Color(0, 255, 0)) # Blue wipe
multiColorWipe(Color(0, 0, 255), Color(0, 0, 255)) # Green wipe
multiColorWipe(Color(255, 255, 255), Color(255, 255, 255)) # Composite White wipe
multiColorWipe(Color(0, 0, 0, 255), Color(0, 0, 0)) # White wipe
multiColorWipe(Color(255, 255, 255, 255), Color(0, 0, 0)) # Composite White + White LED wipe

@ -0,0 +1,72 @@
# Based on NeoPixel library and strandtest example by Tony DiCola (tony@tonydicola.com)
# To be used with a 12x1 NeoPixel LED stripe.
# Place the LEDs in a circle an watch the time go by ...
# red = hours
# blue = minutes 1-5
# green = seconds
# (To run the program permanently and with autostart use systemd.)
import time
import datetime
import math
from neopixel import *
# LED strip configuration:
LED_COUNT = 12 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
# True to invert the signal (when using NPN transistor level shift)
LED_INVERT = False
# Main program logic follows:
if __name__ == '__main__':
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(
LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS)
# Intialize the library (must be called once before other functions).
strip.begin()
for i in range(0, strip.numPixels(), 1):
strip.setPixelColor(i, Color(0, 0, 0))
while True:
now = datetime.datetime.now()
# Low light during 19-8 o'clock
if(8 < now.hour < 19):
strip.setBrightness(200)
else:
strip.setBrightness(25)
hour = now.hour % 12
minute = now.minute / 5
second = now.second / 5
secondmodulo = now.second % 5
timeslot_in_microseconds = secondmodulo * 1000000 + now.microsecond
for i in range(0, strip.numPixels(), 1):
secondplusone = second + 1 if(second < 11) else 0
secondminusone = second - 1 if(second > 0) else 11
colorarray = [0, 0, 0]
if i == second:
if timeslot_in_microseconds < 2500000:
colorarray[0] = int(
0.0000508 * timeslot_in_microseconds) + 126
else:
colorarray[0] = 382 - \
int(0.0000508 * timeslot_in_microseconds)
if i == secondplusone:
colorarray[0] = int(0.0000256 * timeslot_in_microseconds)
if i == secondminusone:
colorarray[0] = int(
0.0000256 * timeslot_in_microseconds) * -1 + 128
if i == minute:
colorarray[2] = 200
if i == hour:
colorarray[1] = 200
strip.setPixelColor(
i, Color(colorarray[0], colorarray[1], colorarray[2]))
strip.show()
time.sleep(0.1)

@ -0,0 +1,115 @@
#!/usr/bin/env python3
# NeoPixel library strandtest example
# Author: Tony DiCola (tony@tonydicola.com)
#
# Direct port of the Arduino NeoPixel library strandtest example. Showcases
# various animations on a strip of NeoPixels.
import time
from neopixel import *
import argparse
# LED strip configuration:
LED_COUNT = 16 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (18 uses PWM!).
#LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 255 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
# Define functions which animate LEDs in various ways.
def colorWipe(strip, color, wait_ms=50):
"""Wipe color across display a pixel at a time."""
for i in range(strip.numPixels()):
strip.setPixelColor(i, color)
strip.show()
time.sleep(wait_ms/1000.0)
def theaterChase(strip, color, wait_ms=50, iterations=10):
"""Movie theater light style chaser animation."""
for j in range(iterations):
for q in range(3):
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, color)
strip.show()
time.sleep(wait_ms/1000.0)
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, 0)
def wheel(pos):
"""Generate rainbow colors across 0-255 positions."""
if pos < 85:
return Color(pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return Color(255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return Color(0, pos * 3, 255 - pos * 3)
def rainbow(strip, wait_ms=20, iterations=1):
"""Draw rainbow that fades across all pixels at once."""
for j in range(256*iterations):
for i in range(strip.numPixels()):
strip.setPixelColor(i, wheel((i+j) & 255))
strip.show()
time.sleep(wait_ms/1000.0)
def rainbowCycle(strip, wait_ms=20, iterations=5):
"""Draw rainbow that uniformly distributes itself across all pixels."""
for j in range(256*iterations):
for i in range(strip.numPixels()):
strip.setPixelColor(i, wheel((int(i * 256 / strip.numPixels()) + j) & 255))
strip.show()
time.sleep(wait_ms/1000.0)
def theaterChaseRainbow(strip, wait_ms=50):
"""Rainbow movie theater light style chaser animation."""
for j in range(256):
for q in range(3):
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, wheel((i+j) % 255))
strip.show()
time.sleep(wait_ms/1000.0)
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, 0)
# Main program logic follows:
if __name__ == '__main__':
# Process arguments
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--clear', action='store_true', help='clear the display on exit')
args = parser.parse_args()
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL)
# Intialize the library (must be called once before other functions).
strip.begin()
print ('Press Ctrl-C to quit.')
if not args.clear:
print('Use "-c" argument to clear LEDs on exit')
try:
while True:
print ('Color wipe animations.')
colorWipe(strip, Color(255, 0, 0)) # Red wipe
colorWipe(strip, Color(0, 255, 0)) # Blue wipe
colorWipe(strip, Color(0, 0, 255)) # Green wipe
print ('Theater chase animations.')
theaterChase(strip, Color(127, 127, 127)) # White theater chase
theaterChase(strip, Color(127, 0, 0)) # Red theater chase
theaterChase(strip, Color( 0, 0, 127)) # Blue theater chase
print ('Rainbow animations.')
rainbow(strip)
rainbowCycle(strip)
theaterChaseRainbow(strip)
except KeyboardInterrupt:
if args.clear:
colorWipe(strip, Color(0,0,0), 10)

@ -0,0 +1,332 @@
#!/usr/bin/env python
"""Bootstrap setuptools installation
To use setuptools in your package's setup.py, include this
file in the same directory and add this to the top of your setup.py::
from ez_setup import use_setuptools
use_setuptools()
To require a specific version of setuptools, set a download
mirror, or use an alternate download directory, simply supply
the appropriate options to ``use_setuptools()``.
This file can also be run as a script to install or upgrade setuptools.
"""
import os
import shutil
import sys
import tempfile
import zipfile
import optparse
import subprocess
import platform
import textwrap
import contextlib
from distutils import log
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
try:
from site import USER_SITE
except ImportError:
USER_SITE = None
DEFAULT_VERSION = "5.7"
DEFAULT_URL = "https://pypi.python.org/packages/source/s/setuptools/"
def _python_cmd(*args):
"""
Return True if the command succeeded.
"""
args = (sys.executable,) + args
return subprocess.call(args) == 0
def _install(archive_filename, install_args=()):
with archive_context(archive_filename):
# installing
log.warn('Installing Setuptools')
if not _python_cmd('setup.py', 'install', *install_args):
log.warn('Something went wrong during the installation.')
log.warn('See the error message above.')
# exitcode will be 2
return 2
def _build_egg(egg, archive_filename, to_dir):
with archive_context(archive_filename):
# building an egg
log.warn('Building a Setuptools egg in %s', to_dir)
_python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
# returning the result
log.warn(egg)
if not os.path.exists(egg):
raise IOError('Could not build the egg.')
class ContextualZipFile(zipfile.ZipFile):
"""
Supplement ZipFile class to support context manager for Python 2.6
"""
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
self.close()
def __new__(cls, *args, **kwargs):
"""
Construct a ZipFile or ContextualZipFile as appropriate
"""
if hasattr(zipfile.ZipFile, '__exit__'):
return zipfile.ZipFile(*args, **kwargs)
return super(ContextualZipFile, cls).__new__(cls)
@contextlib.contextmanager
def archive_context(filename):
# extracting the archive
tmpdir = tempfile.mkdtemp()
log.warn('Extracting in %s', tmpdir)
old_wd = os.getcwd()
try:
os.chdir(tmpdir)
with ContextualZipFile(filename) as archive:
archive.extractall()
# going in the directory
subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
os.chdir(subdir)
log.warn('Now working in %s', subdir)
yield
finally:
os.chdir(old_wd)
shutil.rmtree(tmpdir)
def _do_download(version, download_base, to_dir, download_delay):
egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg'
% (version, sys.version_info[0], sys.version_info[1]))
if not os.path.exists(egg):
archive = download_setuptools(version, download_base,
to_dir, download_delay)
_build_egg(egg, archive, to_dir)
sys.path.insert(0, egg)
# Remove previously-imported pkg_resources if present (see
# https://bitbucket.org/pypa/setuptools/pull-request/7/ for details).
if 'pkg_resources' in sys.modules:
del sys.modules['pkg_resources']
import setuptools
setuptools.bootstrap_install_from = egg
def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, download_delay=15):
to_dir = os.path.abspath(to_dir)
rep_modules = 'pkg_resources', 'setuptools'
imported = set(sys.modules).intersection(rep_modules)
try:
import pkg_resources
except ImportError:
return _do_download(version, download_base, to_dir, download_delay)
try:
pkg_resources.require("setuptools>=" + version)
return
except pkg_resources.DistributionNotFound:
return _do_download(version, download_base, to_dir, download_delay)
except pkg_resources.VersionConflict as VC_err:
if imported:
msg = textwrap.dedent("""
The required version of setuptools (>={version}) is not available,
and can't be installed while this script is running. Please
install a more recent version first, using
'easy_install -U setuptools'.
(Currently using {VC_err.args[0]!r})
""").format(VC_err=VC_err, version=version)
sys.stderr.write(msg)
sys.exit(2)
# otherwise, reload ok
del pkg_resources, sys.modules['pkg_resources']
return _do_download(version, download_base, to_dir, download_delay)
def _clean_check(cmd, target):
"""
Run the command to download target. If the command fails, clean up before
re-raising the error.
"""
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError:
if os.access(target, os.F_OK):
os.unlink(target)
raise
def download_file_powershell(url, target):
"""
Download the file at url to target using Powershell (which will validate
trust). Raise an exception if the command cannot complete.
"""
target = os.path.abspath(target)
ps_cmd = (
"[System.Net.WebRequest]::DefaultWebProxy.Credentials = "
"[System.Net.CredentialCache]::DefaultCredentials; "
"(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)"
% vars()
)
cmd = [
'powershell',
'-Command',
ps_cmd,
]
_clean_check(cmd, target)
def has_powershell():
if platform.system() != 'Windows':
return False
cmd = ['powershell', '-Command', 'echo test']
with open(os.path.devnull, 'wb') as devnull:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
return True
download_file_powershell.viable = has_powershell
def download_file_curl(url, target):
cmd = ['curl', '-L', url, '--silent', '--output', target]
_clean_check(cmd, target)
def has_curl():
cmd = ['curl', '--version']
with open(os.path.devnull, 'wb') as devnull:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
return True
download_file_curl.viable = has_curl
def download_file_wget(url, target):
cmd = ['wget', url, '--quiet', '--output-document', target]
_clean_check(cmd, target)
def has_wget():
cmd = ['wget', '--version']
with open(os.path.devnull, 'wb') as devnull:
try:
subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
except Exception:
return False
return True
download_file_wget.viable = has_wget
def download_file_insecure(url, target):
"""
Use Python to download the file, even though it cannot authenticate the
connection.
"""
src = urlopen(url)
try:
# Read all the data in one block.
data = src.read()
finally:
src.close()
# Write all the data in one block to avoid creating a partial file.
with open(target, "wb") as dst:
dst.write(data)
download_file_insecure.viable = lambda: True
def get_best_downloader():
downloaders = (
download_file_powershell,
download_file_curl,
download_file_wget,
download_file_insecure,
)
viable_downloaders = (dl for dl in downloaders if dl.viable())
return next(viable_downloaders, None)
def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
to_dir=os.curdir, delay=15, downloader_factory=get_best_downloader):
"""
Download setuptools from a specified location and return its filename
`version` should be a valid setuptools version number that is available
as an sdist for download under the `download_base` URL (which should end
with a '/'). `to_dir` is the directory where the egg will be downloaded.
`delay` is the number of seconds to pause before an actual download
attempt.
``downloader_factory`` should be a function taking no arguments and
returning a function for downloading a URL to a target.
"""
# making sure we use the absolute path
to_dir = os.path.abspath(to_dir)
zip_name = "setuptools-%s.zip" % version
url = download_base + zip_name
saveto = os.path.join(to_dir, zip_name)
if not os.path.exists(saveto): # Avoid repeated downloads
log.warn("Downloading %s", url)
downloader = downloader_factory()
downloader(url, saveto)
return os.path.realpath(saveto)
def _build_install_args(options):
"""
Build the arguments to 'python setup.py install' on the setuptools package
"""
return ['--user'] if options.user_install else []
def _parse_args():
"""
Parse the command line for options
"""
parser = optparse.OptionParser()
parser.add_option(
'--user', dest='user_install', action='store_true', default=False,
help='install in user site package (requires Python 2.6 or later)')
parser.add_option(
'--download-base', dest='download_base', metavar="URL",
default=DEFAULT_URL,
help='alternative URL from where to download the setuptools package')
parser.add_option(
'--insecure', dest='downloader_factory', action='store_const',
const=lambda: download_file_insecure, default=get_best_downloader,
help='Use internal, non-validating downloader'
)
parser.add_option(
'--version', help="Specify which version to download",
default=DEFAULT_VERSION,
)
options, args = parser.parse_args()
# positional arguments are ignored
return options
def main():
"""Install or upgrade setuptools and EasyInstall"""
options = _parse_args()
archive = download_setuptools(
version=options.version,
download_base=options.download_base,
downloader_factory=options.downloader_factory,
)
return _install(archive, _build_install_args(options))
if __name__ == '__main__':
sys.exit(main())

@ -0,0 +1,494 @@
0,63,408
1,57,397
2,55,387
3,50,374
4,44,356
5,41,343
6,42,330
7,42,320
8,41,308
9,41,298
10,42,286
11,41,273
12,41,264
13,41,253
14,41,239
15,41,230
16,40,219
17,40,209
18,43,192
19,49,176
20,52,164
21,57,151
22,61,143
23,64,141
24,76,136
25,89,132
26,102,128
27,115,126
28,126,126
29,137,126
30,148,126
31,159,126
32,170,128
33,182,129
34,193,128
35,203,128
36,214,128
37,226,128
38,236,129
39,249,128
40,259,126
41,272,125
42,287,128
43,299,131
44,312,135
45,323,137
46,333,141
47,334,148
48,335,164
49,336,177
50,336,190
51,334,205
52,334,209
53,324,211
54,316,213
55,305,216
56,292,219
57,279,220
58,264,221
59,251,220
60,241,221
61,230,221
62,219,221
63,207,221
64,199,221
65,193,221
66,187,222
67,181,222
68,180,222
69,180,223
70,179,224
71,180,224
72,185,224
73,192,224
74,199,223
75,206,224
76,218,224
77,228,224
78,244,226
79,260,230
80,272,233
81,283,235
82,293,237
83,304,238
84,305,243
85,305,253
86,305,267
87,305,282
88,309,293
89,301,300
90,293,301
91,284,302
92,270,306
93,257,310
94,241,315
95,229,316
96,217,315
97,206,316
98,199,316
99,192,316
100,187,316
101,181,316
102,183,317
103,182,318
104,182,319
105,186,319
106,189,319
107,197,319
108,203,319
109,211,319
110,223,319
111,234,319
112,244,318
113,255,318
114,269,318
115,280,317
116,296,318
117,307,320
118,321,322
119,330,325
120,339,329
121,345,335
122,348,346
123,349,362
124,349,376
125,349,391
126,344,401
127,334,405
128,322,408
129,310,412
130,295,416
131,280,419
132,270,420
133,259,419
134,248,420
135,238,421
136,227,419
137,215,419
138,205,419
139,193,419
140,182,419
141,171,419
142,160,419
143,149,419
144,138,420
145,127,420
146,115,420
147,103,419
148,86,416
149,73,414
150,391,397
151,388,389
152,382,374
153,378,360
154,375,348
155,374,336
156,374,324
157,374,313
158,374,302
159,373,291
160,373,279
161,373,267
162,372,256
163,372,243
164,372,234
165,372,222
166,371,212
167,371,201
168,374,185
169,378,170
170,382,156
171,385,145
172,391,135
173,402,132
174,417,128
175,434,125
176,454,127
177,467,129
178,479,133
179,490,137
180,499,142
181,502,154
182,506,166
183,508,178
184,511,192
185,511,204
186,512,216
187,512,227
188,513,239
189,513,249
190,511,263
191,513,273
192,513,281
193,514,288
194,514,294
195,514,300
196,513,305
197,519,306
198,526,305
199,533,305
200,540,305
201,550,305
202,561,304
203,573,305
204,583,305
205,596,306
206,613,310
207,624,312
208,636,315
209,647,318
210,655,322
211,658,334
212,658,347
213,659,362
214,657,378
215,656,393
216,645,399
217,633,404
218,622,408
219,606,412
220,591,415
221,580,416
222,571,416
223,559,417
224,548,417
225,537,417
226,524,417
227,514,417
228,502,417
229,491,418
230,480,418
231,470,417
232,459,417
233,448,417
234,434,415
235,420,412
236,405,407
237,685,392
238,686,380
239,686,369
240,686,354
241,689,339
242,693,326
243,696,316
244,701,305
245,706,295
246,710,285
247,714,275
248,718,264
249,723,253
250,727,243
251,732,232
252,736,223
253,741,211
254,745,202
255,749,191
256,754,181
257,760,169
258,768,157
259,776,145
260,783,135
261,795,128
262,804,125
263,817,122
264,832,119
265,844,117
266,855,115
267,869,116
268,885,118
269,898,120
270,912,123
271,922,125
272,935,136
273,942,145
274,951,158
275,958,170
276,964,182
277,969,193
278,973,203
279,978,214
280,982,224
281,987,236
282,991,246
283,996,257
284,1000,267
285,1004,276
286,1009,288
287,1013,298
288,1018,309
289,1022,320
290,1026,331
291,1028,348
292,1029,363
293,1030,376
294,1030,389
295,1028,399
296,1018,401
297,1006,404
298,991,408
299,977,414
300,959,414
301,946,412
302,933,411
303,920,409
304,913,405
305,907,400
306,898,394
307,888,393
308,879,392
309,871,391
310,862,390
311,852,391
312,843,392
313,835,393
314,825,394
315,814,395
316,805,398
317,801,403
318,791,412
319,783,410
320,770,412
321,757,414
322,742,415
323,723,409
324,711,405
325,699,403
326,688,399
327,852,285
328,855,280
329,855,277
330,855,275
331,854,273
332,855,268
333,855,263
334,856,255
335,857,255
336,857,260
337,858,267
338,858,273
339,858,275
340,857,277
341,857,279
342,859,284
343,859,287
344,857,286
345,856,286
346,856,286
347,855,286
348,853,288
349,1069,389
350,1065,376
351,1062,363
352,1059,348
353,1057,335
354,1057,323
355,1057,311
356,1058,299
357,1058,288
358,1058,277
359,1057,267
360,1058,252
361,1058,242
362,1059,232
363,1058,224
364,1058,207
365,1058,197
366,1059,184
367,1061,171
368,1064,158
369,1068,144
370,1071,131
371,1079,124
372,1090,121
373,1103,117
374,1114,114
375,1131,110
376,1146,108
377,1158,107
378,1169,108
379,1182,108
380,1194,109
381,1206,109
382,1218,110
383,1230,110
384,1239,112
385,1253,112
386,1266,114
387,1277,111
388,1289,108
389,1302,108
390,1316,108
391,1329,109
392,1341,111
393,1355,115
394,1369,120
395,1383,128
396,1395,137
397,1403,148
398,1409,162
399,1413,177
400,1413,196
401,1413,212
402,1413,223
403,1411,231
404,1406,239
405,1402,245
406,1397,249
407,1403,252
408,1407,255
409,1412,261
410,1414,269
411,1416,279
412,1418,292
413,1420,309
414,1420,327
415,1416,348
416,1413,361
417,1407,372
418,1399,383
419,1388,393
420,1374,400
421,1361,405
422,1349,408
423,1334,411
424,1320,412
425,1308,413
426,1296,414
427,1283,414
428,1271,414
429,1259,414
430,1247,413
431,1234,413
432,1222,413
433,1211,413
434,1200,414
435,1188,413
436,1176,413
437,1164,413
438,1152,413
439,1140,413
440,1125,411
441,1109,407
442,1096,403
443,1083,399
444,1072,396
445,1205,307
446,1207,306
447,1207,304
448,1206,303
449,1205,302
450,1210,300
451,1215,300
452,1221,301
453,1229,302
454,1237,300
455,1247,300
456,1255,302
457,1260,302
458,1265,303
459,1268,303
460,1270,305
461,1269,306
462,1266,307
463,1261,307
464,1254,307
465,1246,307
466,1237,307
467,1228,307
468,1223,307
469,1217,307
470,1210,307
471,1206,211
472,1207,209
473,1207,207
474,1207,206
475,1212,206
476,1218,206
477,1224,207
478,1231,207
479,1238,206
480,1245,206
481,1251,206
482,1256,207
483,1261,207
484,1264,208
485,1263,209
486,1259,209
487,1253,214
488,1247,213
489,1239,212
490,1231,210
491,1224,211
492,1217,214
493,1212,214

@ -0,0 +1,151 @@
# Adafruit NeoPixel library port to the rpi_ws281x library.
# Author: Tony DiCola (tony@tonydicola.com), Jeremy Garff (jer@jers.net)
import atexit
import _rpi_ws281x as ws
def Color(red, green, blue, white = 0):
"""Convert the provided red, green, blue color to a 24-bit color value.
Each color component should be a value 0-255 where 0 is the lowest intensity
and 255 is the highest intensity.
"""
return (white << 24) | (red << 16)| (green << 8) | blue
class _LED_Data(object):
"""Wrapper class which makes a SWIG LED color data array look and feel like
a Python list of integers.
"""
def __init__(self, channel, size):
self.size = size
self.channel = channel
def __getitem__(self, pos):
"""Return the 24-bit RGB color value at the provided position or slice
of positions.
"""
# Handle if a slice of positions are passed in by grabbing all the values
# and returning them in a list.
if isinstance(pos, slice):
return [ws.ws2811_led_get(self.channel, n) for n in xrange(*pos.indices(self.size))]
# Else assume the passed in value is a number to the position.
else:
return ws.ws2811_led_get(self.channel, pos)
def __setitem__(self, pos, value):
"""Set the 24-bit RGB color value at the provided position or slice of
positions.
"""
# Handle if a slice of positions are passed in by setting the appropriate
# LED data values to the provided values.
if isinstance(pos, slice):
index = 0
for n in xrange(*pos.indices(self.size)):
ws.ws2811_led_set(self.channel, n, value[index])
index += 1
# Else assume the passed in value is a number to the position.
else:
return ws.ws2811_led_set(self.channel, pos, value)
class Adafruit_NeoPixel(object):
def __init__(self, num, pin, freq_hz=800000, dma=10, invert=False,
brightness=255, channel=0, strip_type=ws.WS2811_STRIP_RGB):
"""Class to represent a NeoPixel/WS281x LED display. Num should be the
number of pixels in the display, and pin should be the GPIO pin connected
to the display signal line (must be a PWM pin like 18!). Optional
parameters are freq, the frequency of the display signal in hertz (default
800khz), dma, the DMA channel to use (default 10), invert, a boolean
specifying if the signal line should be inverted (default False), and
channel, the PWM channel to use (defaults to 0).
"""
# Create ws2811_t structure and fill in parameters.
self._leds = ws.new_ws2811_t()
# Initialize the channels to zero
for channum in range(2):
chan = ws.ws2811_channel_get(self._leds, channum)
ws.ws2811_channel_t_count_set(chan, 0)
ws.ws2811_channel_t_gpionum_set(chan, 0)
ws.ws2811_channel_t_invert_set(chan, 0)
ws.ws2811_channel_t_brightness_set(chan, 0)
# Initialize the channel in use
self._channel = ws.ws2811_channel_get(self._leds, channel)
ws.ws2811_channel_t_count_set(self._channel, num)
ws.ws2811_channel_t_gpionum_set(self._channel, pin)
ws.ws2811_channel_t_invert_set(self._channel, 0 if not invert else 1)
ws.ws2811_channel_t_brightness_set(self._channel, brightness)
ws.ws2811_channel_t_strip_type_set(self._channel, strip_type)
# Initialize the controller
ws.ws2811_t_freq_set(self._leds, freq_hz)
ws.ws2811_t_dmanum_set(self._leds, dma)
# Grab the led data array.
self._led_data = _LED_Data(self._channel, num)
# Substitute for __del__, traps an exit condition and cleans up properly
atexit.register(self._cleanup)
def _cleanup(self):
# Clean up memory used by the library when not needed anymore.
if self._leds is not None:
ws.delete_ws2811_t(self._leds)
self._leds = None
self._channel = None
def begin(self):
"""Initialize library, must be called once before other functions are
called.
"""
resp = ws.ws2811_init(self._leds)
if resp != ws.WS2811_SUCCESS:
message = ws.ws2811_get_return_t_str(resp)
raise RuntimeError('ws2811_init failed with code {0} ({1})'.format(resp, message))
def show(self):
"""Update the display with the data from the LED buffer."""
resp = ws.ws2811_render(self._leds)
if resp != ws.WS2811_SUCCESS:
message = ws.ws2811_get_return_t_str(resp)
raise RuntimeError('ws2811_render failed with code {0} ({1})'.format(resp, message))
def setPixelColor(self, n, color):
"""Set LED at position n to the provided 24-bit color value (in RGB order).
"""
self._led_data[n] = color
def setPixelColorRGB(self, n, red, green, blue, white = 0):
"""Set LED at position n to the provided red, green, and blue color.
Each color component should be a value from 0 to 255 (where 0 is the
lowest intensity and 255 is the highest intensity).
"""
self.setPixelColor(n, Color(red, green, blue, white))
def setBrightness(self, brightness):
"""Scale each LED in the buffer by the provided brightness. A brightness
of 0 is the darkest and 255 is the brightest.
"""
ws.ws2811_channel_t_brightness_set(self._channel, brightness)
def getBrightness(self):
"""Get the brightness value for each LED in the buffer. A brightness
of 0 is the darkest and 255 is the brightest.
"""
return ws.ws2811_channel_t_brightness_get(self._channel)
def getPixels(self):
"""Return an object which allows access to the LED display data as if
it were a sequence of 24-bit RGB values.
"""
return self._led_data
def numPixels(self):
"""Return the number of pixels in the display."""
return ws.ws2811_channel_t_count_get(self._channel)
def getPixelColor(self, n):
"""Get the 24-bit RGB color value for the LED at position n."""
return self._led_data[n]

@ -0,0 +1,26 @@
For overclocing needs, the pulse times MEASURED on the sign were:
0:
high: 294ns
low: 954ns
1:
high: 626ns
low: 618ns
The HIGH pulse times are always the same, the LOW pulse times are shortened by increasing frequency
Current speed 800Khz
494 LED theoretical maximum framerate:
1/((494*32)/800000 + 80e-6) = 50.4Hz :(
925KHz is still fully in spec of the LEDs and provides:
58.2Hz
955KHz is only slightly out of spec and proviced a smooth
60.1fps

@ -0,0 +1,48 @@
// SWIG interface file to define rpi_ws281x library python wrapper.
// Author: Tony DiCola (tony@tonydicola.com), Jeremy Garff (jer@jers.net)
// Define module name rpi_ws281x. This will actually be imported under
// the name _rpi_ws281x following the SWIG & Python conventions.
%module rpi_ws281x
// Include standard SWIG types & array support for support of uint32_t
// parameters and arrays.
%include "stdint.i"
%include "carrays.i"
// Declare functions which will be exported as anything in the ws2811.h header.
%{
#include "../ws2811.h"
%}
// Process ws2811.h header and export all included functions.
%include "../ws2811.h"
%inline %{
uint32_t ws2811_led_get(ws2811_channel_t *channel, int lednum)
{
if (lednum >= channel->count)
{
return -1;
}
return channel->leds[lednum];
}
int ws2811_led_set(ws2811_channel_t *channel, int lednum, uint32_t color)
{
if (lednum >= channel->count)
{
return -1;
}
channel->leds[lednum] = color;
return 0;
}
ws2811_channel_t *ws2811_channel_get(ws2811_t *ws, int channelnum)
{
return &ws->channel[channelnum];
}
%}

@ -0,0 +1,18 @@
# Python wrapper for the rpi_ws281x library.
# Author: Tony DiCola (tony@tonydicola.com)
from ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, find_packages, Extension
setup(name = 'rpi_ws281x',
version = '1.0.0',
author = 'Jeremy Garff',
author_email = 'jer@jers.net',
description = 'Userspace Raspberry Pi PWM library for WS281X LEDs.',
license = 'MIT',
url = 'https://github.com/jgarff/rpi_ws281x/',
py_modules = ['neopixel'],
ext_modules = [Extension('_rpi_ws281x',
sources=['rpi_ws281x.i'],
library_dirs=['../.'],
libraries=['ws2811', 'rt'])])

@ -0,0 +1,466 @@
/*
* rpihw.c
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <byteswap.h>
#include "rpihw.h"
#define LINE_WIDTH_MAX 80
#define HW_VER_STRING "Revision"
#define PERIPH_BASE_RPI 0x20000000
#define PERIPH_BASE_RPI2 0x3f000000
#define PERIPH_BASE_RPI4 0xfe000000
#define VIDEOCORE_BASE_RPI 0x40000000
#define VIDEOCORE_BASE_RPI2 0xc0000000
#define RPI_MANUFACTURER_MASK (0xf << 16)
#define RPI_WARRANTY_MASK (0x3 << 24)
static const rpi_hw_t rpi_hw_info[] = {
//
// Raspberry Pi 4
//
{
.hwver = 0xA03111,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 1GB"
},
{
.hwver = 0xB03111,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 2GB"
},
{
.hwver = 0xC03111,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 4GB"
},
//
// Model B Rev 1.0
//
{
.hwver = 0x02,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B",
},
{
.hwver = 0x03,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B",
},
//
// Model B Rev 2.0
//
{
.hwver = 0x04,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B",
},
{
.hwver = 0x05,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B",
},
{
.hwver = 0x06,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B",
},
//
// Model A
//
{
.hwver = 0x07,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model A",
},
{
.hwver = 0x08,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model A",
},
{
.hwver = 0x09,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model A",
},
//
// Model B
//
{
.hwver = 0x0d,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B",
},
{
.hwver = 0x0e,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B",
},
{
.hwver = 0x0f,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B",
},
//
// Model B+
//
{
.hwver = 0x10,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B+",
},
{
.hwver = 0x13,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B+",
},
{
.hwver = 0x900032,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model B+",
},
//
// Compute Module
//
{
.hwver = 0x11,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Compute Module 1",
},
{
.hwver = 0x14,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Compute Module 1",
},
//
// Pi Zero
//
{
.hwver = 0x900092,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Pi Zero v1.2",
},
{
.hwver = 0x900093,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Pi Zero v1.3",
},
{
.hwver = 0x920093,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Pi Zero v1.3",
},
{
.hwver = 0x9200c1,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Pi Zero W v1.1",
},
{
.hwver = 0x9000c1,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Pi Zero W v1.1",
},
//
// Model A+
//
{
.hwver = 0x12,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model A+",
},
{
.hwver = 0x15,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model A+",
},
{
.hwver = 0x900021,
.type = RPI_HWVER_TYPE_PI1,
.periph_base = PERIPH_BASE_RPI,
.videocore_base = VIDEOCORE_BASE_RPI,
.desc = "Model A+",
},
//
// Pi 2 Model B
//
{
.hwver = 0xa01041,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 2",
},
{
.hwver = 0xa01040,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 2",
},
{
.hwver = 0xa21041,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 2",
},
//
// Pi 2 with BCM2837
//
{
.hwver = 0xa22042,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 2",
},
//
// Pi 3 Model B
//
{
.hwver = 0xa020d3,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 3 B+",
},
{
.hwver = 0xa02082,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 3",
},
{
.hwver = 0xa02083,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 3",
},
{
.hwver = 0xa22082,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 3",
},
{
.hwver = 0xa22083,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 3",
},
{
.hwver = 0x9020e0,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Model 3 A+",
},
//
// Pi Compute Module 3
//
{
.hwver = 0xa020a0,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 3/L3",
},
//
// Pi Compute Module 3+
//
{
.hwver = 0xa02100,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 3+",
},
};
const rpi_hw_t *rpi_hw_detect(void)
{
const rpi_hw_t *result = NULL;
uint32_t rev;
unsigned i;
#ifdef __aarch64__
// On ARM64, read revision from /proc/device-tree as it is not shown in
// /proc/cpuinfo
FILE *f = fopen("/proc/device-tree/system/linux,revision", "r");
if (!f)
{
return NULL;
}
size_t read = fread(&rev, sizeof(uint32_t), 1, f);
if (read != sizeof(uint32_t))
goto done;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
rev = bswap_32(rev); // linux,revision appears to be in big endian
#endif
for (i = 0; i < (sizeof(rpi_hw_info) / sizeof(rpi_hw_info[0])); i++)
{
uint32_t hwver = rpi_hw_info[i].hwver;
if (rev == hwver)
{
result = &rpi_hw_info[i];
goto done;
}
}
#else
FILE *f = fopen("/proc/cpuinfo", "r");
char line[LINE_WIDTH_MAX];
if (!f)
{
return NULL;
}
while (fgets(line, LINE_WIDTH_MAX - 1, f))
{
if (strstr(line, HW_VER_STRING))
{
char *substr;
substr = strstr(line, ": ");
if (!substr)
{
continue;
}
errno = 0;
rev = strtoul(&substr[1], NULL, 16); // Base 16
if (errno)
{
continue;
}
for (i = 0; i < (sizeof(rpi_hw_info) / sizeof(rpi_hw_info[0])); i++)
{
uint32_t hwver = rpi_hw_info[i].hwver;
// Take out warranty and manufacturer bits
hwver &= ~(RPI_WARRANTY_MASK | RPI_MANUFACTURER_MASK);
rev &= ~(RPI_WARRANTY_MASK | RPI_MANUFACTURER_MASK);
if (rev == hwver)
{
result = &rpi_hw_info[i];
goto done;
}
}
}
}
#endif
done:
fclose(f);
return result;
}

@ -0,0 +1,51 @@
/*
* rpihw.h
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __RPIHW_H__
#define __RPIHW_H__
typedef struct {
uint32_t type;
#define RPI_HWVER_TYPE_UNKNOWN 0
#define RPI_HWVER_TYPE_PI1 1
#define RPI_HWVER_TYPE_PI2 2
#define RPI_HWVER_TYPE_PI4 3
uint32_t hwver;
uint32_t periph_base;
uint32_t videocore_base;
char *desc;
} rpi_hw_t;
const rpi_hw_t *rpi_hw_detect(void);
#endif /* __RPIHW_H__ */

@ -0,0 +1 @@
1.1.0

@ -0,0 +1,71 @@
#
# SConstruct
#
# Copyright (c) 2016 Jeremy Garff <jer @ jers.net>
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted
# provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other materials
# provided with the distribution.
# 3. Neither the name of the owner nor the names of its contributors may be used to endorse
# or promote products derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
import SCons, os
def version_flags(env):
if not env['V']:
env['VERSIONCOMSTR'] = 'Version ${TARGET}'
def version_builders(env):
def generate_version_header(target, source, env):
headername = os.path.basename(target[0].abspath)
headerdef = headername.replace('.', '_').replace('-', '_').upper()
try:
version = open(source[0].abspath, 'r').readline().strip().split('.')
except:
version = [ '0', '0', '0' ]
f = open(headername, 'w')
f.write('/* Auto Generated Header built by version.py - DO NOT MODIFY */\n')
f.write('\n')
f.write('#ifndef __%s__\n' % (headerdef))
f.write('#define __%s__\n' % (headerdef))
f.write('\n')
f.write('#define VERSION_MAJOR %s\n' % version[0])
f.write('#define VERSION_MINOR %s\n' % version[1])
f.write('#define VERSION_MICRO %s\n' % version[2])
f.write('\n')
f.write('#endif /* __%s__ */\n' % (headerdef))
f.close()
env.Append(BUILDERS = {
'Version' : SCons.Builder.Builder(
action = SCons.Action.Action(generate_version_header, '${VERSIONCOMSTR}'),
suffix = '.h',
),
})
def exists(env):
return 1
def generate(env, **kwargs):
[f(env) for f in (version_flags, version_builders)]

1284
ws2811.c

File diff suppressed because it is too large Load Diff

@ -0,0 +1,130 @@
/*
* ws2811.h
*
* Copyright (c) 2014 Jeremy Garff <jer @ jers.net>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
* 3. Neither the name of the owner nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __WS2811_H__
#define __WS2811_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "rpihw.h"
#include "pwm.h"
#define WS2811_TARGET_FREQ 800000 // Can go as low as 400000
// 4 color R, G, B and W ordering
#define SK6812_STRIP_RGBW 0x18100800
#define SK6812_STRIP_RBGW 0x18100008
#define SK6812_STRIP_GRBW 0x18081000
#define SK6812_STRIP_GBRW 0x18080010
#define SK6812_STRIP_BRGW 0x18001008
#define SK6812_STRIP_BGRW 0x18000810
#define SK6812_SHIFT_WMASK 0xf0000000
// 3 color R, G and B ordering
#define WS2811_STRIP_RGB 0x00100800
#define WS2811_STRIP_RBG 0x00100008
#define WS2811_STRIP_GRB 0x00081000
#define WS2811_STRIP_GBR 0x00080010
#define WS2811_STRIP_BRG 0x00001008
#define WS2811_STRIP_BGR 0x00000810
// predefined fixed LED types
#define WS2812_STRIP WS2811_STRIP_GRB
#define SK6812_STRIP WS2811_STRIP_GRB
#define SK6812W_STRIP SK6812_STRIP_GRBW
struct ws2811_device;
typedef uint32_t ws2811_led_t; //< 0xWWRRGGBB
typedef struct ws2811_channel_t
{
int gpionum; //< GPIO Pin with PWM alternate function, 0 if unused
int invert; //< Invert output signal
int count; //< Number of LEDs, 0 if channel is unused
int strip_type; //< Strip color layout -- one of WS2811_STRIP_xxx constants
ws2811_led_t *leds; //< LED buffers, allocated by driver based on count
uint8_t brightness; //< Brightness value between 0 and 255
uint8_t wshift; //< White shift value
uint8_t rshift; //< Red shift value
uint8_t gshift; //< Green shift value
uint8_t bshift; //< Blue shift value
uint8_t *gamma; //< Gamma correction table
} ws2811_channel_t;
typedef struct ws2811_t
{
uint64_t render_wait_time; //< time in µs before the next render can run
struct ws2811_device *device; //< Private data for driver use
const rpi_hw_t *rpi_hw; //< RPI Hardware Information
uint32_t freq; //< Required output frequency
int dmanum; //< DMA number _not_ already in use
ws2811_channel_t channel[RPI_PWM_CHANNELS];
} ws2811_t;
#define WS2811_RETURN_STATES(X) \
X(0, WS2811_SUCCESS, "Success"), \
X(-1, WS2811_ERROR_GENERIC, "Generic failure"), \
X(-2, WS2811_ERROR_OUT_OF_MEMORY, "Out of memory"), \
X(-3, WS2811_ERROR_HW_NOT_SUPPORTED, "Hardware revision is not supported"), \
X(-4, WS2811_ERROR_MEM_LOCK, "Memory lock failed"), \
X(-5, WS2811_ERROR_MMAP, "mmap() failed"), \
X(-6, WS2811_ERROR_MAP_REGISTERS, "Unable to map registers into userspace"), \
X(-7, WS2811_ERROR_GPIO_INIT, "Unable to initialize GPIO"), \
X(-8, WS2811_ERROR_PWM_SETUP, "Unable to initialize PWM"), \
X(-9, WS2811_ERROR_MAILBOX_DEVICE, "Failed to create mailbox device"), \
X(-10, WS2811_ERROR_DMA, "DMA error"), \
X(-11, WS2811_ERROR_ILLEGAL_GPIO, "Selected GPIO not possible"), \
X(-12, WS2811_ERROR_PCM_SETUP, "Unable to initialize PCM"), \
X(-13, WS2811_ERROR_SPI_SETUP, "Unable to initialize SPI"), \
X(-14, WS2811_ERROR_SPI_TRANSFER, "SPI transfer error") \
#define WS2811_RETURN_STATES_ENUM(state, name, str) name = state
#define WS2811_RETURN_STATES_STRING(state, name, str) str
typedef enum {
WS2811_RETURN_STATES(WS2811_RETURN_STATES_ENUM),
WS2811_RETURN_STATE_COUNT
} ws2811_return_t;
ws2811_return_t ws2811_init(ws2811_t *ws2811); //< Initialize buffers/hardware
void ws2811_fini(ws2811_t *ws2811); //< Tear it all down
ws2811_return_t ws2811_render(ws2811_t *ws2811); //< Send LEDs off to hardware
ws2811_return_t ws2811_wait(ws2811_t *ws2811); //< Wait for DMA completion
const char * ws2811_get_return_t_str(const ws2811_return_t state); //< Get string representation of the given return state
#ifdef __cplusplus
}
#endif
#endif /* __WS2811_H__ */
Loading…
Cancel
Save