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');
|
||||
|
@ -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__ */
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
@ -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;
|
||||
}
|
||||
|
@ -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__ */
|
@ -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,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)]
|
||||
|
||||
|
@ -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…
Reference in new issue