Initial commit for Raspberry Pi GPIO ARGB controller

This commit is contained in:
Adam Honse
2024-07-22 01:15:15 -05:00
parent d834b18a16
commit fc411345a3
35 changed files with 4974 additions and 0 deletions

View File

@@ -0,0 +1,138 @@
/*---------------------------------------------------------*\
| RGBController_RaspberryPi_Linux.cpp |
| |
| RGBController for Raspberry Pi GPIO ARGB |
| |
| Adam Honse (CalcProgrammer1) 21 Jul 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include "RGBController_RaspberryPi_Linux.h"
/**------------------------------------------------------------------*\
@name Raspberry Pi
@category Motherboard
@type GPIO
@save :x:
@direct :white_check_mark:
@effects :x:
@detectors DetectRaspberryPiControllers
@comment
\*-------------------------------------------------------------------*/
RGBController_RaspberryPi::RGBController_RaspberryPi(RaspberryPiController* controller_ptr)
{
controller = controller_ptr;
name = "Raspberry Pi";
type = DEVICE_TYPE_MOTHERBOARD;
vendor = "Raspberry Pi";
description = "Raspberry Pi GPIO Device";
location = controller->GetDeviceLocation();
mode Direct;
Direct.name = "Direct";
Direct.value = 0;
Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR;
Direct.color_mode = MODE_COLORS_PER_LED;
modes.push_back(Direct);
SetupZones();
}
void RGBController_RaspberryPi::SetupZones()
{
/*-------------------------------------------------*\
| Only set LED count on the first run |
\*-------------------------------------------------*/
bool first_run = false;
if(zones.size() == 0)
{
first_run = true;
}
/*-------------------------------------------------*\
| Clear any existing color/LED configuration |
\*-------------------------------------------------*/
leds.clear();
colors.clear();
zones.resize(1);
/*-------------------------------------------------*\
| Set zones and leds |
\*-------------------------------------------------*/
for (unsigned int channel_idx = 0; channel_idx < 1; channel_idx++)
{
char ch_idx_string[2];
snprintf(ch_idx_string, 2, "%d", channel_idx + 1);
zones[channel_idx].name = "Channel ";
zones[channel_idx].name.append(ch_idx_string);
zones[channel_idx].type = ZONE_TYPE_LINEAR;
zones[channel_idx].leds_min = 0;
zones[channel_idx].leds_max = 1000;
if(first_run)
{
zones[channel_idx].leds_count = 0;
}
zones[channel_idx].matrix_map = NULL;
for (unsigned int led_ch_idx = 0; led_ch_idx < zones[channel_idx].leds_count; led_ch_idx++)
{
char led_idx_string[4];
snprintf(led_idx_string, 4, "%d", led_ch_idx + 1);
led new_led;
new_led.name = "Channel ";
new_led.name.append(ch_idx_string);
new_led.name.append(", LED ");
new_led.name.append(led_idx_string);
leds.push_back(new_led);
}
}
controller->SetSize(zones[0].leds_count);
SetupColors();
}
void RGBController_RaspberryPi::ResizeZone(int zone, int new_size)
{
if((size_t) zone >= zones.size())
{
return;
}
if(((unsigned int)new_size >= zones[zone].leds_min) && ((unsigned int)new_size <= zones[zone].leds_max))
{
zones[zone].leds_count = new_size;
SetupZones();
}
}
void RGBController_RaspberryPi::DeviceUpdateLEDs()
{
DeviceUpdateMode();
}
void RGBController_RaspberryPi::UpdateZoneLEDs(int /*zone*/)
{
DeviceUpdateLEDs();
}
void RGBController_RaspberryPi::UpdateSingleLED(int /*led*/)
{
DeviceUpdateLEDs();
}
void RGBController_RaspberryPi::DeviceUpdateMode()
{
controller->SetColors(&colors[0]);
}

View File

@@ -0,0 +1,33 @@
/*---------------------------------------------------------*\
| RGBController_RaspberryPi_Linux.h |
| |
| RGBController for Raspberry Pi GPIO ARGB |
| |
| Adam Honse (CalcProgrammer1) 21 Jul 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#pragma once
#include "RaspberryPiController_Linux.h"
#include "RGBController.h"
class RGBController_RaspberryPi : public RGBController
{
public:
RGBController_RaspberryPi(RaspberryPiController* controller_ptr);
void SetupZones();
void ResizeZone(int zone, int new_size);
void DeviceUpdateLEDs();
void UpdateZoneLEDs(int zone);
void UpdateSingleLED(int led);
void DeviceUpdateMode();
private:
RaspberryPiController* controller;
};

View File

@@ -0,0 +1,36 @@
/*---------------------------------------------------------*\
| RaspberryPiControllerDetect_Linux.cpp |
| |
| Detector for Raspberry Pi GPIO ARGB |
| |
| Adam Honse (CalcProgrammer1) 21 Jul 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include <vector>
#include "Detector.h"
#include "RaspberryPiController_Linux.h"
#include "RGBController_RaspberryPi_Linux.h"
/******************************************************************************************\
* *
* DetectRaspberryPiControllers *
* *
* Detect Raspberry Pi controllers *
* *
\******************************************************************************************/
void DetectRaspberryPiControllers()
{
RaspberryPiController* controller = new RaspberryPiController();
if(controller->Initialize())
{
RGBController_RaspberryPi* rgb_controller = new RGBController_RaspberryPi(controller);
ResourceManager::get()->RegisterRGBController(rgb_controller);
}
}
REGISTER_DETECTOR("Raspberry Pi", DetectRaspberryPiControllers);

View File

@@ -0,0 +1,73 @@
/*---------------------------------------------------------*\
| RaspberryPiController_Linux.cpp |
| |
| Driver for Raspberry Pi GPIO ARGB |
| |
| Adam Honse (CalcProgrammer1) 21 Jul 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#include "LogManager.h"
#include "RaspberryPiController_Linux.h"
RaspberryPiController::RaspberryPiController()
{
memset(&rpi_ws2811, 0x00, sizeof(rpi_ws2811));
rpi_ws2811.freq = WS2811_TARGET_FREQ;
rpi_ws2811.dmanum = RPI_WS2811_DMA;
rpi_ws2811.render_wait_time = 0;
rpi_ws2811.channel[0].gpionum = RPI_WS2811_GPIO;
rpi_ws2811.channel[0].invert = 0;
rpi_ws2811.channel[0].count = 0;
rpi_ws2811.channel[0].strip_type = WS2811_STRIP_GBR;
rpi_ws2811.channel[0].brightness = 255;
rpi_ws2811.channel[1].gpionum = 0;
rpi_ws2811.channel[1].invert = 0;
rpi_ws2811.channel[1].count = 0;
rpi_ws2811.channel[1].strip_type = 0;
rpi_ws2811.channel[1].brightness = 0;
}
RaspberryPiController::~RaspberryPiController()
{
ws2811_fini(&rpi_ws2811);
}
std::string RaspberryPiController::GetDeviceLocation()
{
return("GPIO: 13, DMA: 10");
}
bool RaspberryPiController::Initialize()
{
if(ws2811_init(&rpi_ws2811) != WS2811_SUCCESS)
{
LOG_ERROR( "RaspberryPi: ws2811_init() failure");
return(false);
}
return(true);
}
void RaspberryPiController::SetColors(RGBColor * colors)
{
for(int i = 0; i < 2; i++)
{
rpi_ws2811.channel[0].leds[i] = colors[i];
}
ws2811_render(&rpi_ws2811);
}
void RaspberryPiController::SetSize(unsigned int new_size)
{
rpi_ws2811.channel[0].count = new_size;
ws2811_fini(&rpi_ws2811);
Initialize();
}

View File

@@ -0,0 +1,35 @@
/*---------------------------------------------------------*\
| RaspberryPiController_Linux.h |
| |
| Driver for Raspberry Pi GPIO ARGB |
| |
| Adam Honse (CalcProgrammer1) 21 Jul 2024 |
| |
| This file is part of the OpenRGB project |
| SPDX-License-Identifier: GPL-2.0-only |
\*---------------------------------------------------------*/
#pragma once
#include <string>
#include "RGBController.h"
#include "ws2811.h"
#define RPI_WS2811_DMA 10
#define RPI_WS2811_GPIO 18
class RaspberryPiController
{
public:
RaspberryPiController();
~RaspberryPiController();
std::string GetDeviceLocation();
bool Initialize();
void SetColors(RGBColor * colors);
void SetSize(unsigned int new_size);
private:
ws2811_t rpi_ws2811;
};

View File

@@ -468,6 +468,9 @@ contains(QMAKE_PLATFORM, linux) {
i2c_smbus/i2c_smbus_linux.h \
AutoStart/AutoStart-Linux.h \
INCLUDEPATH += \
dependencies/rpi_ws281x/ \
LIBS += \
-lmbedx509 \
-lmbedtls \
@@ -508,6 +511,12 @@ contains(QMAKE_PLATFORM, linux) {
SOURCES += \
dependencies/hueplusplus-1.1.0/src/LinHttpHandler.cpp \
dependencies/rpi_ws281x/dma.c \
dependencies/rpi_ws281x/mailbox.c \
dependencies/rpi_ws281x/pcm.c \
dependencies/rpi_ws281x/pwm.c \
dependencies/rpi_ws281x/rpihw.c \
dependencies/rpi_ws281x/ws2811.c \
i2c_smbus/i2c_smbus_linux.cpp \
scsiapi/scsiapi_linux.c \
serial_port/find_usb_serial_port_linux.cpp \

13
dependencies/rpi_ws281x/.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
.sconsign.dblite
version.h
*.pyc
test
newtest
*.o
*.a
*.swp
build/
release/
debug/
settings.json

88
dependencies/rpi_ws281x/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,88 @@
cmake_minimum_required(VERSION 3.0.0)
# read and parse version file
file(READ version PROJECT_VERSION)
string(STRIP ${PROJECT_VERSION} PROJECT_VERSION)
string(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" VERSION_MAJOR ${PROJECT_VERSION})
string(REGEX REPLACE "[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" VERSION_MINOR ${PROJECT_VERSION})
string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" VERSION_MICRO ${PROJECT_VERSION})
set(HEADERDEF "${VERSION_MAJOR}_${VERSION_MINOR}_${VERSION_MICRO}")
project(rpi_ws281x VERSION ${PROJECT_VERSION})
option(BUILD_SHARED "Build as shared library" OFF)
option(BUILD_TEST "Build test application" ON)
set(CMAKE_C_STANDARD 11)
set(LIB_TARGET ws2811)
set(TEST_TARGET test)
set(LIB_PUBLIC_HEADERS
ws2811.h
rpihw.h
pwm.h
clk.h
dma.h
gpio.h
mailbox.h
pcm.h
)
set(LIB_SOURCES
mailbox.c
ws2811.c
pwm.c
pcm.c
dma.c
rpihw.c
)
set(TEST_SOURCES
main.c
)
include(GNUInstallDirs)
configure_file(version.h.in version.h)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/pkg-config.pc.in"
"${CMAKE_CURRENT_BINARY_DIR}/libws2811.pc"
@ONLY
)
set(DEST_HEADERS_DIR include/ws2811)
set(DEST_LIB_DIR lib)
if(BUILD_SHARED)
add_library(${LIB_TARGET} SHARED ${LIB_SOURCES})
else()
add_library(${LIB_TARGET} ${LIB_SOURCES})
endif()
target_link_libraries(${LIB_TARGET} m)
set_target_properties(${LIB_TARGET} PROPERTIES PUBLIC_HEADER "${LIB_PUBLIC_HEADERS}")
install(TARGETS ${LIB_TARGET}
ARCHIVE DESTINATION ${DEST_LIB_DIR}
PUBLIC_HEADER DESTINATION ${DEST_HEADERS_DIR}
)
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/libws2811.pc"
DESTINATION lib/pkgconfig)
install(CODE "execute_process(COMMAND /sbin/ldconfig
RESULT_VARIABLE EXIT_STATUS
ERROR_QUIET)
if (NOT EXIT_STATUS EQUAL 0)
message(\"Warning: Could not run ldconfig. You may need to manually run ldconfig as root to cache the newly installed libraries.\")
endif()")
if(BUILD_TEST)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_executable(${TEST_TARGET} ${TEST_SOURCES})
target_link_libraries(${TEST_TARGET} ${LIB_TARGET})
endif()

View File

@@ -0,0 +1,9 @@
package: libws2811
Version: 1.1.0-1
Section: base
Priority: optional
Architecture: armhf
Depends:
Maintainer: Jeremy Garff (jer@jers.net)
Description: Raspberry Pi WS281X Library
LED Control Library for the Raspberry Pi.

45
dependencies/rpi_ws281x/DEBIAN/postinst vendored Normal file
View File

@@ -0,0 +1,45 @@
#!/bin/sh
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
# source debconf library
. /usr/share/debconf/confmodule
# Source dbconfig-common functions
if [ -f /usr/share/dbconfig-common/dpkg/postinst.pgsql ]; then
. /usr/share/dbconfig-common/dpkg/postinst.pgsql
fi
case "$1" in
configure)
ldconfig
;;
abort-upgrade|abort-remove|abort-deconfigure)
exit 0
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
db_stop
exit 0
~

45
dependencies/rpi_ws281x/DEBIAN/postrm vendored Normal file
View File

@@ -0,0 +1,45 @@
#!/bin/sh
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
# source debconf library
. /usr/share/debconf/confmodule
# Source dbconfig-common functions
if [ -f /usr/share/dbconfig-common/dpkg/postinst.pgsql ]; then
. /usr/share/dbconfig-common/dpkg/postinst.pgsql
fi
case "$1" in
remove)
ldconfig
;;
abort-upgrade|abort-remove|abort-deconfigure)
exit 0
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac
db_stop
exit 0
~

44
dependencies/rpi_ws281x/DEBIAN/prerm vendored Normal file
View File

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

24
dependencies/rpi_ws281x/LICENSE vendored Normal file
View File

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

235
dependencies/rpi_ws281x/README.md vendored Normal file
View File

@@ -0,0 +1,235 @@
rpi_ws281x
==========
Userspace Raspberry Pi library for controlling WS281X LEDs.
This includes WS2812 and SK6812RGB RGB LEDs
Preliminary support is now included for SK6812RGBW LEDs (yes, RGB + W)
The LEDs can be controlled by either the PWM (2 independent channels)
or PCM controller (1 channel) or the SPI interface (1 channel).
### Bindings:
Language-specific bindings for rpi_ws281x are available in:
* Python - https://github.com/rpi-ws281x/rpi-ws281x-python
* Rust - https://github.com/rpi-ws281x/rpi-ws281x-rust
* Powershell - https://github.com/rpi-ws281x/rpi-ws281x-powershell
* Java - https://github.com/rpi-ws281x/rpi-ws281x-java
* CSharp - https://github.com/rpi-ws281x/rpi-ws281x-csharp
* Go - https://github.com/rpi-ws281x/rpi-ws281x-go
### Background:
The BCM2835 in the Raspberry Pi has both a PWM and a PCM module that
are well suited to driving individually controllable WS281X LEDs.
Using the DMA, PWM or PCM FIFO, and serial mode in the PWM, it's
possible to control almost any number of WS281X LEDs in a chain connected
to the appropriate output pin.
For SPI the Raspbian spidev driver is used (`/dev/spidev0.0`).
This library and test program set the clock rate to 3X the desired output
frequency and creates a bit pattern in RAM from an array of colors where
each bit is represented by 3 bits as follows.
Bit 1 - 1 1 0
Bit 0 - 1 0 0
### GPIO Usage:
The GPIOs that can be used are limited by the hardware of the Pi and will
vary based on the method used to drive them (PWM, PCM or SPI).
Beware that the GPIO numbers are not the same as the physical pin numbers
on the header.
PWM:
```
PWM0, which can be set to use GPIOs 12, 18, 40, and 52.
Only 12 (pin 32) and 18 (pin 12) are available on the B+/2B/3B
PWM1 which can be set to use GPIOs 13, 19, 41, 45 and 53.
Only 13 is available on the B+/2B/PiZero/3B, on pin 33
```
PCM:
```
PCM_DOUT, which can be set to use GPIOs 21 and 31.
Only 21 is available on the B+/2B/PiZero/3B, on pin 40.
```
SPI:
```
SPI0-MOSI is available on GPIOs 10 and 38.
Only GPIO 10 is available on all models.
See also note for RPi 3 below.
```
### Power and voltage requirements
WS281X LEDs are generally driven at 5V. Depending on your actual
LED model and data line length you might be able to successfully drive
the data input with 3.3V. However in the general case you probably
want to use a level shifter to convert from the Raspberry Pi GPIO/PWM to 5V.
It is also possible to run the LEDs from a 3.3V - 3.6V power source, and
connect the GPIO directly at a cost of brightness, but this isn't
recommended.
The test program is designed to drive a 8x8 grid of LEDs e.g.from
Adafruit (http://www.adafruit.com/products/1487) or Pimoroni
(https://shop.pimoroni.com/products/unicorn-hat).
Please see the Adafruit and Pimoroni websites for more information.
Know what you're doing with the hardware and electricity. I take no
reponsibility for damage, harm, or mistakes.
### Build:
#### Build with SCons:
- Install Scons (on raspbian, `apt-get install scons`).
- Make sure to adjust the parameters in main.c to suit your hardware.
- Signal rate (400kHz to 800kHz). Default 800kHz.
- ledstring.invert=1 if using a inverting level shifter.
- Width and height of LED matrix (height=1 for LED string).
- Type `scons` from inside the source directory.
#### Build and install with CMake:
- Install CMake
- Configure your build:
For example:
```
mkdir build
cd build
cmake -D BUILD_SHARED=OFF -D BUILD_TEST=ON ..
```
See also for available options in `CMakeLists.txt`.
- Type `cmake --build .` to build
- To install built binaries and headers into your system type:
```
sudo make install
```
### Running:
- Type `sudo ./test` (default uses PWM channel 0).
- That's it. You should see a moving rainbow scroll across the
display.
- More options are available, `./test -h` should show them:
```
./test version 1.1.0
Usage: ./test
-h (--help) - this information
-s (--strip) - strip type - rgb, grb, gbr, rgbw
-x (--width) - matrix width (default 8)
-y (--height) - matrix height (default 8)
-d (--dma) - dma channel to use (default 10)
-g (--gpio) - GPIO to use
If omitted, default is 18 (PWM0)
-i (--invert) - invert pin output (pulse LOW)
-c (--clear) - clear matrix on exit.
-v (--version) - version information
```
### Important warning about DMA channels
You must make sure that the DMA channel you choose to use for the LEDs is not [already in use](https://www.raspberrypi.org/forums/viewtopic.php?p=609380#p609380) by the operating system.
For example, **using DMA channel 5 [will cause](https://github.com/jgarff/rpi_ws281x/issues/224) filesystem corruption** on the Raspberry Pi 3 Model B.
The default DMA channel (10) should be safe for the Raspberry Pi 3 Model B, but this may change in future software releases.
### Limitations:
#### PWM
Since this library and the onboard Raspberry Pi audio
both use the PWM, they cannot be used together. You will need to
blacklist the Broadcom audio kernel module by creating a file
`/etc/modprobe.d/snd-blacklist.conf` with
blacklist snd_bcm2835
If the audio device is still loading after blacklisting, you may also
need to comment it out in the /etc/modules file.
On headless systems you may also need to force audio through hdmi
Edit config.txt and add:
hdmi_force_hotplug=1
hdmi_force_edid_audio=1
A reboot is required for this change to take effect
Some distributions use audio by default, even if nothing is being played.
If audio is needed, you can use a USB audio device instead.
#### PCM
When using PCM you cannot use digital audio devices which use I2S since I2S
uses the PCM hardware, but you can use analog audio.
#### SPI
When using SPI the led string is the only device which can be connected to
the SPI bus. Both digital (I2S/PCM) and analog (PWM) audio can be used.
Many distributions have a maximum SPI transfer of 4096 bytes. This can be
changed in `/boot/cmdline.txt` by appending
```
spidev.bufsiz=32768
```
On an RPi 3 you have to change the GPU core frequency to 250 MHz, otherwise
the SPI clock has the wrong frequency.
Do this by adding the following line to /boot/config.txt and reboot:
```
core_freq=250
```
On an RPi 4 you must set a fixed frequency to avoid the idle CPU scaling changing the SPI frequency and breaking the ws281x timings:
Do this by adding the following lines to /boot/config.txt and reboot:
```
core_freq=500
core_freq_min=500
```
SPI requires you to be in the `gpio` group if you wish to control your LEDs
without root.
### Comparison PWM/PCM/SPI
Both PWM and PCM use DMA transfer to output the control signal for the LEDs.
The max size of a DMA transfer is 65536 bytes. Since each LED needs 12 bytes
(4 colors, 8 symbols per color, 3 bits per symbol) this means you can
control approximately 5400 LEDs for a single strand in PCM and 2700 LEDs per string
for PWM (Only PWM can control 2 independent strings simultaneously)
SPI uses the SPI device driver in the kernel. For transfers larger than
96 bytes the kernel driver also uses DMA.
Of course there are practical limits on power and signal quality. These will
be more constraining in practice than the theoretical limits above.
When controlling a LED string of 240 LEDs the CPU load on the original Pi 2 (BCM2836) are:
PWM 5%
PCM 5%
SPI 1%
### Usage:
The API is very simple. Make sure to create and initialize the `ws2811_t`
structure as seen in [`main.c`](main.c). From there it can be initialized
by calling `ws2811_init()`. LEDs are changed by modifying the color in
the `.led[index]` array and calling `ws2811_render()`.
The rest is handled by the library, which either creates the DMA memory and
starts the DMA for PWM and PCM or prepares the SPI transfer buffer and sends
it out on the MISO pin.
Make sure to hook a signal handler for SIGKILL to do cleanup. From the
handler make sure to call `ws2811_fini()`. It'll make sure that the DMA
is finished before program execution stops and cleans up after itself.

95
dependencies/rpi_ws281x/SConscript vendored Normal file
View File

@@ -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", 0o755)
])
)
package = tools_env.Command('%s.deb' % package_name, package_files,
'cd %s; dpkg-deb --build %s' % (Dir('.').abspath, package_name));
Alias("deb", package)

77
dependencies/rpi_ws281x/SConstruct vendored Normal file
View File

@@ -0,0 +1,77 @@
#
# 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",
"-lm",
],
},
],
]
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');

66
dependencies/rpi_ws281x/clk.h vendored Normal file
View File

@@ -0,0 +1,66 @@
/*
* 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__
#include <stdint.h>
typedef struct {
uint32_t ctl;
#define CM_CLK_CTL_PASSWD (0x5a << 24)
#define CM_CLK_CTL_MASH(val) ((val & 0x3) << 9)
#define CM_CLK_CTL_FLIP (1 << 8)
#define CM_CLK_CTL_BUSY (1 << 7)
#define CM_CLK_CTL_KILL (1 << 5)
#define CM_CLK_CTL_ENAB (1 << 4)
#define CM_CLK_CTL_SRC_GND (0 << 0)
#define CM_CLK_CTL_SRC_OSC (1 << 0)
#define CM_CLK_CTL_SRC_TSTDBG0 (2 << 0)
#define CM_CLK_CTL_SRC_TSTDBG1 (3 << 0)
#define CM_CLK_CTL_SRC_PLLA (4 << 0)
#define CM_CLK_CTL_SRC_PLLC (5 << 0)
#define CM_CLK_CTL_SRC_PLLD (6 << 0)
#define CM_CLK_CTL_SRC_HDMIAUX (7 << 0)
uint32_t div;
#define CM_CLK_DIV_PASSWD (0x5a << 24)
#define CM_CLK_DIV_DIVI(val) ((val & 0xfff) << 12)
#define CM_CLK_DIV_DIVF(val) ((val & 0xfff) << 0)
} __attribute__((packed, aligned(4))) cm_clk_t;
/*
* PWM and PCM clock offsets from https://www.scribd.com/doc/127599939/BCM2835-Audio-clocks
*
*/
#define CM_PCM_OFFSET (0x00101098)
#define CM_PWM_OFFSET (0x001010a0)
#endif /* __CLK_H__ */

78
dependencies/rpi_ws281x/dma.c vendored Normal file
View File

@@ -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];
}

127
dependencies/rpi_ws281x/dma.h vendored Normal file
View File

@@ -0,0 +1,127 @@
/*
* 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__
#include <stdint.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__ */

109
dependencies/rpi_ws281x/gpio.h vendored Normal file
View File

@@ -0,0 +1,109 @@
/*
* 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__
#include <stdint.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__ */

84
dependencies/rpi_ws281x/linux.py vendored Normal file
View File

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

292
dependencies/rpi_ws281x/mailbox.c vendored Normal file
View File

@@ -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);
}

49
dependencies/rpi_ws281x/mailbox.h vendored Normal file
View File

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

419
dependencies/rpi_ws281x/main.c vendored Normal file
View File

@@ -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,
.invert = 0,
.count = LED_COUNT,
.strip_type = STRIP_TYPE,
.brightness = 255,
},
[1] =
{
.gpionum = 0,
.invert = 0,
.count = 0,
.brightness = 0,
},
},
};
ws2811_led_t *matrix;
static uint8_t running = 1;
void matrix_render(void)
{
int x, y;
for (x = 0; x < width; x++)
{
for (y = 0; y < height; y++)
{
ledstring.channel[0].leds[(y * width) + x] = matrix[y * width + x];
}
}
}
void matrix_raise(void)
{
int x, y;
for (y = 0; y < (height - 1); y++)
{
for (x = 0; x < width; x++)
{
// This is for the 8x8 Pimoroni Unicorn-HAT where the LEDS in subsequent
// rows are arranged in opposite directions
matrix[y * width + x] = matrix[(y + 1)*width + width - x - 1];
}
}
}
void matrix_clear(void)
{
int x, y;
for (y = 0; y < (height ); y++)
{
for (x = 0; x < width; x++)
{
matrix[y * width + x] = 0;
}
}
}
int dotspos[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
ws2811_led_t dotcolors[] =
{
0x00200000, // red
0x00201000, // orange
0x00202000, // yellow
0x00002000, // green
0x00002020, // lightblue
0x00000020, // blue
0x00100010, // purple
0x00200010, // pink
};
ws2811_led_t dotcolors_rgbw[] =
{
0x00200000, // red
0x10200000, // red + W
0x00002000, // green
0x10002000, // green + W
0x00000020, // blue
0x10000020, // blue + W
0x00101010, // white
0x10101010, // white + W
};
void matrix_bottom(void)
{
int i;
for (i = 0; i < (int)(ARRAY_SIZE(dotspos)); i++)
{
dotspos[i]++;
if (dotspos[i] > (width - 1))
{
dotspos[i] = 0;
}
if (ledstring.channel[0].strip_type == SK6812_STRIP_RGBW) {
matrix[dotspos[i] + (height - 1) * width] = dotcolors_rgbw[i];
} else {
matrix[dotspos[i] + (height - 1) * width] = dotcolors[i];
}
}
}
static void ctrl_c_handler(int signum)
{
(void)(signum);
running = 0;
}
static void setup_handlers(void)
{
struct sigaction sa =
{
.sa_handler = ctrl_c_handler,
};
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
}
void parseargs(int argc, char **argv, ws2811_t *ws2811)
{
int index;
int c;
static struct option longopts[] =
{
{"help", no_argument, 0, 'h'},
{"dma", required_argument, 0, 'd'},
{"gpio", required_argument, 0, 'g'},
{"invert", no_argument, 0, 'i'},
{"clear", no_argument, 0, 'c'},
{"strip", required_argument, 0, 's'},
{"height", required_argument, 0, 'y'},
{"width", required_argument, 0, 'x'},
{"version", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
while (1)
{
index = 0;
c = getopt_long(argc, argv, "cd:g:his:vx:y:", longopts, &index);
if (c == -1)
break;
switch (c)
{
case 0:
/* handle flag options (array's 3rd field non-0) */
break;
case 'h':
fprintf(stderr, "%s version %s\n", argv[0], VERSION);
fprintf(stderr, "Usage: %s \n"
"-h (--help) - this information\n"
"-s (--strip) - strip type - rgb, grb, gbr, rgbw\n"
"-x (--width) - matrix width (default 8)\n"
"-y (--height) - matrix height (default 8)\n"
"-d (--dma) - dma channel to use (default 10)\n"
"-g (--gpio) - GPIO to use\n"
" If omitted, default is 18 (PWM0)\n"
"-i (--invert) - invert pin output (pulse LOW)\n"
"-c (--clear) - clear matrix on exit.\n"
"-v (--version) - version information\n"
, argv[0]);
exit(-1);
case 'D':
break;
case 'g':
if (optarg) {
int gpio = atoi(optarg);
/*
PWM0, which can be set to use GPIOs 12, 18, 40, and 52.
Only 12 (pin 32) and 18 (pin 12) are available on the B+/2B/3B
PWM1 which can be set to use GPIOs 13, 19, 41, 45 and 53.
Only 13 is available on the B+/2B/PiZero/3B, on pin 33
PCM_DOUT, which can be set to use GPIOs 21 and 31.
Only 21 is available on the B+/2B/PiZero/3B, on pin 40.
SPI0-MOSI is available on GPIOs 10 and 38.
Only GPIO 10 is available on all models.
The library checks if the specified gpio is available
on the specific model (from model B rev 1 till 3B)
*/
ws2811->channel[0].gpionum = gpio;
}
break;
case 'i':
ws2811->channel[0].invert=1;
break;
case 'c':
clear_on_exit=1;
break;
case 'd':
if (optarg) {
int dma = atoi(optarg);
if (dma < 14) {
ws2811->dmanum = dma;
} else {
printf ("invalid dma %d\n", dma);
exit (-1);
}
}
break;
case 'y':
if (optarg) {
height = atoi(optarg);
if (height > 0) {
ws2811->channel[0].count = height * width;
} else {
printf ("invalid height %d\n", height);
exit (-1);
}
}
break;
case 'x':
if (optarg) {
width = atoi(optarg);
if (width > 0) {
ws2811->channel[0].count = height * width;
} else {
printf ("invalid width %d\n", width);
exit (-1);
}
}
break;
case 's':
if (optarg) {
if (!strncasecmp("rgb", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_RGB;
}
else if (!strncasecmp("rbg", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_RBG;
}
else if (!strncasecmp("grb", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_GRB;
}
else if (!strncasecmp("gbr", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_GBR;
}
else if (!strncasecmp("brg", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_BRG;
}
else if (!strncasecmp("bgr", optarg, 4)) {
ws2811->channel[0].strip_type = WS2811_STRIP_BGR;
}
else if (!strncasecmp("rgbw", optarg, 4)) {
ws2811->channel[0].strip_type = SK6812_STRIP_RGBW;
}
else if (!strncasecmp("grbw", optarg, 4)) {
ws2811->channel[0].strip_type = SK6812_STRIP_GRBW;
}
else {
printf ("invalid strip %s\n", optarg);
exit (-1);
}
}
break;
case 'v':
fprintf(stderr, "%s version %s\n", argv[0], VERSION);
exit(-1);
case '?':
/* getopt_long already reported error? */
exit(-1);
default:
exit(-1);
}
}
}
int main(int argc, char *argv[])
{
ws2811_return_t ret;
sprintf(VERSION, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO);
parseargs(argc, argv, &ledstring);
matrix = malloc(sizeof(ws2811_led_t) * width * height);
setup_handlers();
if ((ret = ws2811_init(&ledstring)) != WS2811_SUCCESS)
{
fprintf(stderr, "ws2811_init failed: %s\n", ws2811_get_return_t_str(ret));
return ret;
}
while (running)
{
matrix_raise();
matrix_bottom();
matrix_render();
if ((ret = ws2811_render(&ledstring)) != WS2811_SUCCESS)
{
fprintf(stderr, "ws2811_render failed: %s\n", ws2811_get_return_t_str(ret));
break;
}
// 15 frames /sec
usleep(1000000 / 15);
}
if (clear_on_exit) {
matrix_clear();
matrix_render();
ws2811_render(&ledstring);
}
ws2811_fini(&ledstring);
printf ("\n");
return ret;
}

127
dependencies/rpi_ws281x/pcm.c vendored Normal file
View File

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

159
dependencies/rpi_ws281x/pcm.h vendored Normal file
View File

@@ -0,0 +1,159 @@
/*
* 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__
#include <stdint.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__ */

View File

@@ -0,0 +1,9 @@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@/ws2811
Name: libws2811
Description: Raspberry Pi WS281X Library
Version: @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_MICRO@
Requires:
Libs: -L${libdir} -lws2811
Cflags: -I${includedir}

104
dependencies/rpi_ws281x/pwm.c vendored Normal file
View File

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

123
dependencies/rpi_ws281x/pwm.h vendored Normal file
View File

@@ -0,0 +1,123 @@
/*
* 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__
#include <stdint.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__ */

637
dependencies/rpi_ws281x/rpihw.c vendored Normal file
View File

@@ -0,0 +1,637 @@
/*
* 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 400
//
{
.hwver = 0xc03130,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 400 - 4GB v1.0"
},
{
.hwver = 0xc03131,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 400 - 4GB v1.1"
},
//
// 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 v1.1"
},
{
.hwver = 0xB03111,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 2GB v.1.1"
},
{
.hwver = 0xC03111,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 4GB v1.1"
},
{
.hwver = 0xA03112,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 1GB v1.2"
},
{
.hwver = 0xB03112,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 2GB v.1.2"
},
{
.hwver = 0xC03112,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 4GB v1.2"
},
{
.hwver = 0xb03114,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 2GB v1.4"
},
{
.hwver = 0xD03114,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 8GB v1.4"
},
{
.hwver = 0xc03114,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 4GB v1.4"
},
{
.hwver = 0xa03115,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 1GB v1.5"
},
{
.hwver = 0xb03115,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 2GB v1.5"
},
{
.hwver = 0xc03115,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 4GB v1.5"
},
{
.hwver = 0xd03115,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 4 Model B - 8GB v1.5"
},
//
// Compute Module 4
//
{
.hwver = 0xa03140,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 4 v1.0 eMMC"
},
{
.hwver = 0xb03140,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 4 v1.0 Lite"
},
{
.hwver = 0xc03140,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 4 v1.0 WiFi"
},
{
.hwver = 0xd03140,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 4 v1.0 WiFi 8GB"
},
{
.hwver = 0xa03141,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 4 Rev 1.1"
},
{
.hwver = 0xb03141,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 4 Rev 1.1"
},
{
.hwver = 0xc03141,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 4 Rev 1.1"
},
{
.hwver = 0xd03141,
.type = RPI_HWVER_TYPE_PI4,
.periph_base = PERIPH_BASE_RPI4,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 4 Rev 1.1"
},
//
// 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",
},
{
.hwver = 0xa020a0,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 3/L3",
},
{
.hwver = 0xa02100,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 3+",
},
{
.hwver = 0xa220a0,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Compute Module 3 Rev 1.0",
},
//
// 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 Zero 2 W
//
{
.hwver = 0x902120,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi Zero 2 W v1.0",
},
//
// 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 = 0xa020d4,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 3 B+",
},
{
.hwver = 0xa020d3,
.type = RPI_HWVER_TYPE_PI2,
.periph_base = PERIPH_BASE_RPI2,
.videocore_base = VIDEOCORE_BASE_RPI2,
.desc = "Pi 3 B+",
},
{
.hwver = 0xa32082,
.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+",
}
};
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, 1, sizeof(uint32_t), 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;
}

52
dependencies/rpi_ws281x/rpihw.h vendored Normal file
View File

@@ -0,0 +1,52 @@
/*
* 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__
#include <stdint.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__ */

10
dependencies/rpi_ws281x/version.h.in vendored Normal file
View File

@@ -0,0 +1,10 @@
/* Auto Generated Header built by version.py - DO NOT MODIFY */
#ifndef __@HEADERDEF@__
#define __@HEADERDEF@__
#define VERSION_MAJOR @VERSION_MAJOR@
#define VERSION_MINOR @VERSION_MINOR@
#define VERSION_MICRO @VERSION_MICRO@
#endif /* __@HEADERDEF@__ */

71
dependencies/rpi_ws281x/version.py vendored Normal file
View File

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

1326
dependencies/rpi_ws281x/ws2811.c vendored Normal file
View File

File diff suppressed because it is too large Load Diff

133
dependencies/rpi_ws281x/ws2811.h vendored Normal file
View File

@@ -0,0 +1,133 @@
/*
* 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 <stdint.h>
#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
void ws2811_set_custom_gamma_factor(ws2811_t *ws2811, double gamma_factor); //< Set a custom Gamma correction array based on a gamma correction factor
#ifdef __cplusplus
}
#endif
#endif /* __WS2811_H__ */