mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Merge branch 'HEAD' of https://github.com/tvdzwan/hyperion.git
Conflicts: bin/install_hyperion.sh deploy/hyperion.conf Former-commit-id: 3a51538a8d50f7f3198a044c29200ec6dba4e931
This commit is contained in:
commit
e24420c6d4
@ -32,6 +32,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall")
|
||||
# Configure the use of QT4
|
||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED QUIET)
|
||||
|
||||
# add protocol buffers
|
||||
find_package(Protobuf REQUIRED)
|
||||
|
||||
#SET(QT_DONT_USE_QTGUI TRUE)
|
||||
#SET(QT_USE_QTCONSOLE TRUE)
|
||||
include(${QT_USE_FILE})
|
||||
|
14
README.md
14
README.md
@ -1,10 +1,14 @@
|
||||
HYPERION
|
||||
========
|
||||
|
||||
An opensource 'AmbiLight' implementation controlled using the RaspBerry Pi running Raspbmc.
|
||||
The intention is to replace BobLight. The replacement includes several 'improvements':
|
||||
* Frame capture of screen included in deamon. This reduces the processor usages for image based led control to less than 2%.
|
||||
* Priority channel can specificy a timeout on their 'command'. This allows a client or remote control to specify a fixed color and then close the connection.
|
||||
* Json IP-control interface. Easy to use interface based on json format for control over TCP/IP.
|
||||
Hyperion is an opensource 'AmbiLight' implementation controlled using the RaspBerry Pi running [Raspbmc](http://www.raspbmc.com). The main features of Hyperion are:
|
||||
* Low CPU load. For a led string of 50 leds the CPU usage will typically be below 1.5% on a non-overclocked Pi.
|
||||
* Json interface which allows easy integration into scripts.
|
||||
* A command line utility allows easy testing and configuration of the color transforms (Transformation settings are not preserved over a restart at the moment...).
|
||||
* Priority channels are not coupled to a specific led data provider which means that a provider can post led data and leave without the need to maintain a connection to Hyperion. This is ideal for a remote application (like our Android app).
|
||||
* HyperCon. A tool which helps generate a Hyperion configuration file.
|
||||
* Generic software architecture to support new devices and new algorithms easily.
|
||||
|
||||
More information can be found on the [wiki](https://github.com/tvdzwan/hyperion/wiki).
|
||||
|
||||
The source is released under MIT-License (see http://opensource.org/licenses/MIT).
|
||||
|
16
bin/copy_binaries_to_deploy.sh
Executable file
16
bin/copy_binaries_to_deploy.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$#" -ne 2 ] || ! [ -d "$1" ] || ! [ -d "$2" ]; then
|
||||
echo "Usage: $0 <BUILD-DIR> <REPO-DIR>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
builddir="$1"
|
||||
repodir="$2"
|
||||
echo build directory = $builddir
|
||||
echo repository root dirrectory = $repodir
|
||||
|
||||
echo Copying binaries
|
||||
cp -v "$builddir"/bin/hyperiond "$repodir"/deploy
|
||||
cp -v "$builddir"/bin/hyperion-remote "$repodir"/deploy
|
||||
cp -v "$builddir"/bin/gpio2spi "$repodir"/deploy
|
@ -13,15 +13,22 @@ fi
|
||||
# Stop hyperion daemon if it is running
|
||||
initctl stop hyperion
|
||||
|
||||
# Copy the hyperion-binaries to the /usr/bin
|
||||
wget raw.github.com/tvdzwan/hyperion/master/deploy/hyperiond -P /usr/bin/
|
||||
wget raw.github.com/tvdzwan/hyperion/master/deploy/hyperion-remote -P /usr/bin/
|
||||
wget -N github.com/tvdzwan/hyperion/raw/master/deploy/hyperiond -P /usr/bin/
|
||||
wget -N github.com/tvdzwan/hyperion/raw/master/deploy/hyperion-remote -P /usr/bin/
|
||||
|
||||
# Copy the gpio changer (gpio->spi) to the /usr/bin
|
||||
wget -N github.com/tvdzwan/hyperion/raw/master/deploy/gpio2spi -P /usr/bin/
|
||||
|
||||
# Copy the hyperion configuration file to /etc
|
||||
wget raw.github.com/tvdzwan/hyperion/master/config/hyperion.config.json -P /etc/
|
||||
wget -N github.com/tvdzwan/hyperion/raw/master/config/hyperion.config.json -P /etc/
|
||||
|
||||
# Copy the service control configuration to /etc/int
|
||||
wget raw.github.com/tvdzwan/hyperion/master/bin/hyperion.conf -P /etc/init/
|
||||
wget -N github.com/tvdzwan/hyperion/raw/master/deploy/hyperion.conf -P /etc/init/
|
||||
|
||||
# Set permissions
|
||||
chmod +x /usr/bin/hyperiond
|
||||
chmod +x /usr/bin/hyperion-remote
|
||||
chmod +x /usr/bin/gpio2spi
|
||||
|
||||
# Start the hyperion daemon
|
||||
initctl start hyperion
|
||||
|
@ -1,333 +1,372 @@
|
||||
// Hyperion configuration
|
||||
// Automatically generated configuration file for 'Hyperion daemon'
|
||||
// Generated by: HyperCon (The Hyperion deamon configuration file builder
|
||||
|
||||
{
|
||||
/// Device configuration contains the following fields:
|
||||
/// * 'name' : The user friendly name of the device (only used for display purposes)
|
||||
/// * 'type' : The type of the device or leds (known types for now are 'ws2801', 'test' and 'none')
|
||||
/// * 'output' : The output specification depends on selected device
|
||||
/// - 'ws2801' this is the device (eg '/dev/spidev0.0')
|
||||
/// - 'test' this is the file used to write test output (eg '/home/pi/hyperion.out')
|
||||
/// * 'rate' : The baudrate of the output to the device (only applicable for 'ws2801')
|
||||
"device" :
|
||||
{
|
||||
"name" : "MyPi",
|
||||
"type" : "ws2801",
|
||||
"output" : "/dev/spidev0.0",
|
||||
"interval" : 20000,
|
||||
"rate" : 48000
|
||||
"rate" : 1000000
|
||||
},
|
||||
|
||||
/// Color manipulation configuration used to tune the output colors to specific surroundings. Contains the following fields:
|
||||
/// * 'hsv' : The manipulation in the Hue-Saturation-Value color domain with the following tuning parameters:
|
||||
/// - 'saturationGain' The gain adjustement of the saturation
|
||||
/// - 'valueGain' The gain adjustement of the value
|
||||
/// * 'red'/'green'/'blue' : The manipulation in the Red-Green-Blue color domain with the following tuning parameters for each channel:
|
||||
/// - 'threshold' The minimum required input value for the channel to be on (else zero)
|
||||
/// - 'gamma' The gamma-curve correction factor
|
||||
/// - 'blacklevel' The lowest possible value (when the channel is black)
|
||||
/// - 'whitelevel' The highest possible value (when the channel is white)
|
||||
"color" :
|
||||
{
|
||||
"hsv" : {
|
||||
"saturationGain" : 1.0,
|
||||
"valueGain" : 1.0
|
||||
"hsv" :
|
||||
{
|
||||
"saturationGain" : 1.0000,
|
||||
"valuGain" : 1.5000
|
||||
},
|
||||
"red" :
|
||||
{
|
||||
"threshold" : 0.0,
|
||||
"gamma" : 1.0,
|
||||
"blacklevel" : 0.0,
|
||||
"whitelevel" : 1.0
|
||||
"threshold" : 0.1000,
|
||||
"gamma" : 2.0000,
|
||||
"blacklevel" : 0.0000,
|
||||
"whitelevel" : 0.8000
|
||||
},
|
||||
"green" :
|
||||
{
|
||||
"threshold" : 0.0,
|
||||
"gamma" : 1.0,
|
||||
"blacklevel" : 0.0,
|
||||
"whitelevel" : 1.0
|
||||
"threshold" : 0.1000,
|
||||
"gamma" : 2.0000,
|
||||
"blacklevel" : 0.0000,
|
||||
"whitelevel" : 1.0000
|
||||
},
|
||||
"blue" :
|
||||
{
|
||||
"threshold" : 0.0,
|
||||
"gamma" : 1.0,
|
||||
"blacklevel" : 0.0,
|
||||
"whitelevel" : 1.0
|
||||
"threshold" : 0.1000,
|
||||
"gamma" : 2.0000,
|
||||
"blacklevel" : 0.0000,
|
||||
"whitelevel" : 1.0000
|
||||
}
|
||||
},
|
||||
|
||||
/// The configuration for each individual led. This contains the specification of the area
|
||||
/// averaged of an input image for each led to determine its color. Each item in the list
|
||||
/// contains the following fields:
|
||||
/// * index: The index of the led. This determines its location in the string of leds; zero
|
||||
/// being the first led.
|
||||
/// * hscan: The fractional part of the image along the horizontal used for the averaging
|
||||
/// (minimum and maximum inclusive)
|
||||
/// * vscan: The fractional part of the image along the vertical used for the averaging
|
||||
/// (minimum and maximum inclusive)
|
||||
"leds" :
|
||||
[
|
||||
{
|
||||
"index" : 0,
|
||||
"hscan" : { "minimum" : 47.0588, "maximum" : 52.9412 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 1,
|
||||
"hscan" : { "minimum" : 41.1765, "maximum" : 47.0588 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 2,
|
||||
"hscan" : { "minimum" : 35.2941, "maximum" : 41.1765 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 3,
|
||||
"hscan" : { "minimum" : 29.4118, "maximum" : 35.2941 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 4,
|
||||
"hscan" : { "minimum" : 23.5294, "maximum" : 29.4118 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 5,
|
||||
"hscan" : { "minimum" : 17.6471, "maximum" : 23.5294 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 6,
|
||||
"hscan" : { "minimum" : 11.7647, "maximum" : 17.6471 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 7,
|
||||
"hscan" : { "minimum" : 5.88235, "maximum" : 11.7647 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
// TOP-LEFT Corner
|
||||
{
|
||||
"index" : 8,
|
||||
"hscan" : { "minimum" : 0, "maximum" : 5.88235 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 9,
|
||||
"hscan" : { "minimum" : 0, "maximum" : 10 },
|
||||
"vscan" : { "minimum" : 10, "maximum" : 20 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 10,
|
||||
"hscan" : { "minimum" : 0, "maximum" : 10 },
|
||||
"vscan" : { "minimum" : 20, "maximum" : 30 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 }
|
||||
},
|
||||
{
|
||||
"index" : 11,
|
||||
"hscan" : { "minimum" : 0, "maximum" : 10 },
|
||||
"vscan" : { "minimum" : 30, "maximum" : 40 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 }
|
||||
},
|
||||
{
|
||||
"index" : 12,
|
||||
"hscan" : { "minimum" : 0, "maximum" : 10 },
|
||||
"vscan" : { "minimum" : 40, "maximum" : 50 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 }
|
||||
},
|
||||
{
|
||||
"index" : 13,
|
||||
"hscan" : { "minimum" : 0, "maximum" : 10 },
|
||||
"vscan" : { "minimum" : 50, "maximum" : 60 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 }
|
||||
},
|
||||
{
|
||||
"index" : 14,
|
||||
"hscan" : { "minimum" : 0, "maximum" : 10 },
|
||||
"vscan" : { "minimum" : 60, "maximum" : 70 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 }
|
||||
},
|
||||
{
|
||||
"index" : 15,
|
||||
"hscan" : { "minimum" : 0, "maximum" : 10 },
|
||||
"vscan" : { "minimum" : 70, "maximum" : 80 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 }
|
||||
},
|
||||
{
|
||||
"index" : 16,
|
||||
"hscan" : { "minimum" : 0, "maximum" : 10 },
|
||||
"vscan" : { "minimum" : 80, "maximum" : 90 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0500 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
// BOTTOM-LEFT Corner
|
||||
{
|
||||
"index" : 17,
|
||||
"hscan" : { "minimum" : 0, "maximum" : 5.88235 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.0000, "maximum" : 0.0625 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 18,
|
||||
"hscan" : { "minimum" : 5.88235, "maximum" : 11.7647 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.0625, "maximum" : 0.1250 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 19,
|
||||
"hscan" : { "minimum" : 11.7647, "maximum" : 17.6471 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.1250, "maximum" : 0.1875 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 20,
|
||||
"hscan" : { "minimum" : 17.6471, "maximum" : 23.5294 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.1875, "maximum" : 0.2500 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 21,
|
||||
"hscan" : { "minimum" : 23.5294, "maximum" : 29.4118 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.2500, "maximum" : 0.3125 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 22,
|
||||
"hscan" : { "minimum" : 29.4118, "maximum" : 35.2941 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.3125, "maximum" : 0.3750 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 23,
|
||||
"hscan" : { "minimum" : 35.2941, "maximum" : 41.1765 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.3750, "maximum" : 0.4375 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 24,
|
||||
"hscan" : { "minimum" : 41.1765, "maximum" : 47.0588 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.4375, "maximum" : 0.5000 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 25,
|
||||
"hscan" : { "minimum" : 47.0588, "maximum" : 52.9412 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 26,
|
||||
"hscan" : { "minimum" : 52.9412, "maximum" : 58.8235 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 27,
|
||||
"hscan" : { "minimum" : 58.8235, "maximum" : 64.7059 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 28,
|
||||
"hscan" : { "minimum" : 64.7059, "maximum" : 70.5882 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 29,
|
||||
"hscan" : { "minimum" : 70.5882, "maximum" : 76.4706 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 30,
|
||||
"hscan" : { "minimum" : 76.4706, "maximum" : 82.3529 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 31,
|
||||
"hscan" : { "minimum" : 82.3529, "maximum" : 88.2353 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 32,
|
||||
"hscan" : { "minimum" : 88.2353, "maximum" : 94.1176 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
// BOTTOM-RIGHT Corner
|
||||
{
|
||||
"index" : 33,
|
||||
"hscan" : { "minimum" : 94.1176, "maximum" : 100 },
|
||||
"vscan" : { "minimum" : 90, "maximum" : 100 }
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.0800 }
|
||||
},
|
||||
{
|
||||
"index" : 34,
|
||||
"hscan" : { "minimum" : 90, "maximum" : 100 },
|
||||
"vscan" : { "minimum" : 80, "maximum" : 90 }
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.0000, "maximum" : 0.1429 }
|
||||
},
|
||||
{
|
||||
"index" : 35,
|
||||
"hscan" : { "minimum" : 90, "maximum" : 100 },
|
||||
"vscan" : { "minimum" : 70, "maximum" : 80 }
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.1429, "maximum" : 0.2857 }
|
||||
},
|
||||
{
|
||||
"index" : 36,
|
||||
"hscan" : { "minimum" : 90, "maximum" : 100 },
|
||||
"vscan" : { "minimum" : 60, "maximum" : 70 }
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.2857, "maximum" : 0.4286 }
|
||||
},
|
||||
{
|
||||
"index" : 37,
|
||||
"hscan" : { "minimum" : 90, "maximum" : 100 },
|
||||
"vscan" : { "minimum" : 50, "maximum" : 60 }
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.4286, "maximum" : 0.5714 }
|
||||
},
|
||||
{
|
||||
"index" : 38,
|
||||
"hscan" : { "minimum" : 90, "maximum" : 100 },
|
||||
"vscan" : { "minimum" : 40, "maximum" : 50 }
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.5714, "maximum" : 0.7143 }
|
||||
},
|
||||
{
|
||||
"index" : 39,
|
||||
"hscan" : { "minimum" : 90, "maximum" : 100 },
|
||||
"vscan" : { "minimum" : 30, "maximum" : 40 }
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.7143, "maximum" : 0.8571 }
|
||||
},
|
||||
{
|
||||
"index" : 40,
|
||||
"hscan" : { "minimum" : 90, "maximum" : 100 },
|
||||
"vscan" : { "minimum" : 20, "maximum" : 30 }
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.8571, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 41,
|
||||
"hscan" : { "minimum" : 90, "maximum" : 100 },
|
||||
"vscan" : { "minimum" : 10, "maximum" : 20 }
|
||||
"hscan" : { "minimum" : 0.9500, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
// TOP-RIGHT Corner
|
||||
{
|
||||
"index" : 42,
|
||||
"hscan" : { "minimum" : 94.1176, "maximum" : 100 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.9375, "maximum" : 1.0000 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 43,
|
||||
"hscan" : { "minimum" : 88.2353, "maximum" : 94.1176 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.8750, "maximum" : 0.9375 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 44,
|
||||
"hscan" : { "minimum" : 82.3529, "maximum" : 88.2353 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.8125, "maximum" : 0.8750 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 45,
|
||||
"hscan" : { "minimum" : 76.4706, "maximum" : 82.3529 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.7500, "maximum" : 0.8125 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 46,
|
||||
"hscan" : { "minimum" : 70.5882, "maximum" : 76.4706 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.6875, "maximum" : 0.7500 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 47,
|
||||
"hscan" : { "minimum" : 64.7059, "maximum" : 70.5882 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.6250, "maximum" : 0.6875 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 48,
|
||||
"hscan" : { "minimum" : 58.8235, "maximum" : 64.7059 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.5625, "maximum" : 0.6250 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
},
|
||||
{
|
||||
"index" : 49,
|
||||
"hscan" : { "minimum" : 52.9412, "maximum" : 58.8235 },
|
||||
"vscan" : { "minimum" : 0, "maximum" : 10 }
|
||||
"hscan" : { "minimum" : 0.5000, "maximum" : 0.5625 },
|
||||
"vscan" : { "minimum" : 0.9200, "maximum" : 1.0000 }
|
||||
}
|
||||
],
|
||||
|
||||
// The XBMC video checker will connect to XBMC to check its player state and adjust the grabbing on it
|
||||
"xbmcVideoChecker" : {
|
||||
// Enable the use of the XBMC checker
|
||||
"enable" : true,
|
||||
|
||||
// Address of the hoxt running XBMC
|
||||
"xbmcAddress" : "127.0.0.1",
|
||||
|
||||
// Port used by XBMC for the TCP json service (Default disabled by XBMC for non-local clients)
|
||||
"xbmcTcpPort" : 9090,
|
||||
|
||||
// Grab screen when XBMC is playing video
|
||||
"grabVideo" : true,
|
||||
|
||||
// Grab screen when XBMC is playing pictures
|
||||
"grabPictures" : true,
|
||||
|
||||
// Grab screen when XBMC is playing audio
|
||||
"grabAudio" : true,
|
||||
|
||||
// Grab screen when XBMC is not playing anything (in menu)
|
||||
"grabMenu" : true
|
||||
},
|
||||
|
||||
/// The boot-sequence configuration, contains the following items:
|
||||
/// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none')
|
||||
/// * duration_ms : The length of the boot-sequence [ms]
|
||||
"bootsequence" :
|
||||
{
|
||||
"type" : "rainbow",
|
||||
"type" : "Rainbow",
|
||||
"duration_ms" : 3000
|
||||
},
|
||||
|
||||
/// The configuration for the frame-grabber, contains the following items:
|
||||
/// * width : The width of the grabbed frames [pixels]
|
||||
/// * height : The height of the grabbed frames [pixels]
|
||||
/// * frequency_Hz : The frequency of the frame grab [Hz]
|
||||
"framegrabber" :
|
||||
{
|
||||
"width" : 64,
|
||||
"height" : 64,
|
||||
"frequency_Hz" : 10
|
||||
"frequency_Hz" : 10.0
|
||||
},
|
||||
|
||||
/// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields:
|
||||
/// * xbmcAddress : The IP address of the XBMC-host
|
||||
/// * xbmcTcpPort : The TCP-port of the XBMC-server
|
||||
/// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback
|
||||
/// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show
|
||||
/// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback
|
||||
/// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu
|
||||
"xbmcVideoChecker" :
|
||||
{
|
||||
"xbmcAddress" : "127.0.0.1",
|
||||
"xbmcTcpPort" : 9090,
|
||||
"grabVideo" : true,
|
||||
"grabPictures" : true,
|
||||
"grabAudio" : true,
|
||||
"grabMenu" : false
|
||||
},
|
||||
|
||||
/// The configuration of the Json server which enables the json remote interface
|
||||
/// * port : Port at which the json server is started
|
||||
"jsonServer" :
|
||||
{
|
||||
"port" : 19444
|
||||
},
|
||||
|
||||
/// The configuration of the Proto server which enables the protobuffer remote interface
|
||||
/// * port : Port at which the protobuffer server is started
|
||||
"protoServer" :
|
||||
{
|
||||
"port" : 19445
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
76f29d2a8a10e60629d08889f183d318dfee9f3f
|
||||
58c9b56f08a3ea76161730b0f8b8f102e8d70143
|
BIN
deploy/gpio2spi
Executable file
BIN
deploy/gpio2spi
Executable file
Binary file not shown.
Binary file not shown.
17
deploy/hyperion.conf
Normal file
17
deploy/hyperion.conf
Normal file
@ -0,0 +1,17 @@
|
||||
## Hyperion daemon
|
||||
|
||||
description "hyperion"
|
||||
author "poljvd & tvdzwan"
|
||||
|
||||
start on (runlevel [2345])
|
||||
stop on (runlevel [!2345])
|
||||
|
||||
respawn
|
||||
|
||||
pre-start script
|
||||
modprobe spidev
|
||||
/usr/bin/gpio2spi
|
||||
end script
|
||||
|
||||
exec /usr/bin/hyperiond /etc/hyperion.config.json
|
||||
|
BIN
deploy/hyperiond
BIN
deploy/hyperiond
Binary file not shown.
1
deploy/hyperiond.REMOVED.git-id
Normal file
1
deploy/hyperiond.REMOVED.git-id
Normal file
@ -0,0 +1 @@
|
||||
cf974e6aa1ff2a7194ce2b82fd5da5fa2373676a
|
59
include/protoserver/ProtoServer.h
Normal file
59
include/protoserver/ProtoServer.h
Normal file
@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
// system includes
|
||||
#include <cstdint>
|
||||
|
||||
// Qt includes
|
||||
#include <QTcpServer>
|
||||
#include <QSet>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
class ProtoClientConnection;
|
||||
|
||||
///
|
||||
/// This class creates a TCP server which accepts connections wich can then send
|
||||
/// in Protocol Buffer encoded commands. This interface to Hyperion is used by
|
||||
/// hyperion-remote to control the leds
|
||||
///
|
||||
class ProtoServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
///
|
||||
/// ProtoServer constructor
|
||||
/// @param hyperion Hyperion instance
|
||||
/// @param port port number on which to start listening for connections
|
||||
///
|
||||
ProtoServer(Hyperion * hyperion, uint16_t port = 19445);
|
||||
~ProtoServer();
|
||||
|
||||
///
|
||||
/// @return the port number on which this TCP listens for incoming connections
|
||||
///
|
||||
uint16_t getPort() const;
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// Slot which is called when a client tries to create a new connection
|
||||
///
|
||||
void newConnection();
|
||||
|
||||
///
|
||||
/// Slot which is called when a client closes a connection
|
||||
/// @param connection The Connection object which is being closed
|
||||
///
|
||||
void closedConnection(ProtoClientConnection * connection);
|
||||
|
||||
private:
|
||||
/// Hyperion instance
|
||||
Hyperion * _hyperion;
|
||||
|
||||
/// The TCP server object
|
||||
QTcpServer _server;
|
||||
|
||||
/// List with open connections
|
||||
QSet<ProtoClientConnection *> _openConnections;
|
||||
};
|
@ -7,5 +7,6 @@ add_subdirectory(bootsequence)
|
||||
add_subdirectory(dispmanx-grabber)
|
||||
add_subdirectory(hyperion)
|
||||
add_subdirectory(jsonserver)
|
||||
add_subdirectory(protoserver)
|
||||
add_subdirectory(utils)
|
||||
add_subdirectory(xbmcvideochecker)
|
||||
|
@ -1,3 +1,6 @@
|
||||
// stl includes
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
|
||||
// Bootsequence includes
|
||||
#include <bootsequence/BootSequenceFactory.h>
|
||||
@ -8,7 +11,8 @@
|
||||
|
||||
BootSequence * BootSequenceFactory::createBootSequence(Hyperion * hyperion, const Json::Value & jsonConfig)
|
||||
{
|
||||
const std::string type = jsonConfig["type"].asString();
|
||||
std::string type = jsonConfig["type"].asString();
|
||||
std::transform(type.begin(), type.end(), type.begin(), ::tolower);
|
||||
|
||||
if (type == "none")
|
||||
{
|
||||
@ -19,7 +23,7 @@ BootSequence * BootSequenceFactory::createBootSequence(Hyperion * hyperion, cons
|
||||
const unsigned duration_ms = jsonConfig["duration_ms"].asUInt();
|
||||
return new RainbowBootSequence(hyperion, duration_ms);
|
||||
}
|
||||
else if (type == "knightrider")
|
||||
else if (type == "knightrider" || type == "knight rider")
|
||||
{
|
||||
const unsigned duration_ms = jsonConfig["duration_ms"].asUInt();
|
||||
return new KittBootSequence(hyperion, duration_ms);
|
||||
|
@ -1,18 +1,6 @@
|
||||
|
||||
#include "DispmanxFrameGrabber.h"
|
||||
|
||||
// Because the shapshot function is incompatible between versions (use of different enum as
|
||||
// third argument) and no proper version number is available as preprocessor define we cast the
|
||||
// function to the same function with the third argument as 'int'.
|
||||
// This way we can call the function in both versions of the VideoCore library without
|
||||
// switching.
|
||||
static int my_vc_dispmanx_snapshot(DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_RESOURCE_HANDLE_T snapshot_resource, int transform)
|
||||
{
|
||||
typedef int (*SnapshotFunctionPtr)(DISPMANX_DISPLAY_HANDLE_T, DISPMANX_RESOURCE_HANDLE_T, int);
|
||||
SnapshotFunctionPtr snapshot = (SnapshotFunctionPtr) &vc_dispmanx_snapshot;
|
||||
return (*snapshot)(display, snapshot_resource, transform);
|
||||
}
|
||||
|
||||
DispmanxFrameGrabber::DispmanxFrameGrabber(const unsigned width, const unsigned height) :
|
||||
_vc_display(0),
|
||||
_vc_resource(0),
|
||||
@ -77,7 +65,7 @@ void DispmanxFrameGrabber::grabFrame(RgbImage& image)
|
||||
_vc_display = vc_dispmanx_display_open(0);
|
||||
|
||||
// Create the snapshot (incl down-scaling)
|
||||
my_vc_dispmanx_snapshot(_vc_display, _vc_resource, _vc_flags);
|
||||
vc_dispmanx_snapshot(_vc_display, _vc_resource, (DISPMANX_TRANSFORM_T) _vc_flags);
|
||||
|
||||
// Read the snapshot into the memory
|
||||
void* image_ptr = image.memptr();
|
||||
|
@ -66,10 +66,10 @@ LedString Hyperion::createLedString(const Json::Value& ledsConfig)
|
||||
led.index = ledConfig["index"].asInt();
|
||||
const Json::Value& hscanConfig = ledConfig["hscan"];
|
||||
const Json::Value& vscanConfig = ledConfig["vscan"];
|
||||
led.minX_frac = std::max(0.0, std::min(100.0, hscanConfig["minimum"].asDouble()))/100.0;
|
||||
led.maxX_frac = std::max(0.0, std::min(100.0, hscanConfig["maximum"].asDouble()))/100.0;
|
||||
led.minY_frac = 1.0 - std::max(0.0, std::min(100.0, vscanConfig["maximum"].asDouble()))/100.0;
|
||||
led.maxY_frac = 1.0 - std::max(0.0, std::min(100.0, vscanConfig["minimum"].asDouble()))/100.0;
|
||||
led.minX_frac = std::max(0.0, std::min(1.0, hscanConfig["minimum"].asDouble()));
|
||||
led.maxX_frac = std::max(0.0, std::min(1.0, hscanConfig["maximum"].asDouble()));
|
||||
led.minY_frac = std::max(0.0, std::min(1.0, vscanConfig["maximum"].asDouble()));
|
||||
led.maxY_frac = std::max(0.0, std::min(1.0, vscanConfig["minimum"].asDouble()));
|
||||
|
||||
ledString.leds().push_back(led);
|
||||
}
|
||||
|
@ -18,33 +18,30 @@
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
},
|
||||
"interval": {
|
||||
"type":"integer",
|
||||
"required":true
|
||||
},
|
||||
"rate" : {
|
||||
"type" : "integer",
|
||||
"required":true
|
||||
"required" : true,
|
||||
"minimum" : 0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"color": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"required":false,
|
||||
"properties": {
|
||||
"hsv" : {
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"saturationGain" : {
|
||||
"type" : "number",
|
||||
"required" : true,
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
},
|
||||
"valueGain" : {
|
||||
"type" : "number",
|
||||
"required" : true,
|
||||
"required" : false,
|
||||
"minimum" : 0.0
|
||||
}
|
||||
},
|
||||
@ -52,77 +49,81 @@
|
||||
},
|
||||
"red": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":true,
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"green": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":true,
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"blue": {
|
||||
"type":"object",
|
||||
"required":true,
|
||||
"required":false,
|
||||
"properties":{
|
||||
"gamma": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
"required":false
|
||||
},
|
||||
"whitelevel": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
"required":false
|
||||
},
|
||||
"blacklevel": {
|
||||
"type":"number",
|
||||
"required":true
|
||||
"required":false
|
||||
},
|
||||
"threshold": {
|
||||
"type":"number",
|
||||
"required":true,
|
||||
"required":false,
|
||||
"minimum" : 0.0,
|
||||
"maximum" : 1.0
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"leds": {
|
||||
"type":"array",
|
||||
@ -146,7 +147,8 @@
|
||||
"type":"number",
|
||||
"required":true
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"vscan": {
|
||||
"type":"object",
|
||||
@ -160,20 +162,18 @@
|
||||
"type":"number",
|
||||
"required":true
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"xbmcVideoChecker" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"enable" : {
|
||||
"type" : "boolean",
|
||||
"required" : true
|
||||
},
|
||||
"xbmcAddress" : {
|
||||
"type" : "string",
|
||||
"required" : true
|
||||
@ -204,7 +204,7 @@
|
||||
"bootsequence" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"type" : {
|
||||
"type" : "string",
|
||||
@ -220,7 +220,7 @@
|
||||
"framegrabber" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : true,
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"width" : {
|
||||
"type" : "integer",
|
||||
@ -236,6 +236,34 @@
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"jsonServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"protoServer" :
|
||||
{
|
||||
"type" : "object",
|
||||
"required" : false,
|
||||
"properties" : {
|
||||
"port" : {
|
||||
"type" : "integer",
|
||||
"required" : true,
|
||||
"minimum" : 0,
|
||||
"maximum" : 65535
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
|
52
libsrc/protoserver/CMakeLists.txt
Normal file
52
libsrc/protoserver/CMakeLists.txt
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
# Define the current source locations
|
||||
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/protoserver)
|
||||
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/protoserver)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${PROTOBUF_INCLUDE_DIRS})
|
||||
|
||||
# Group the headers that go through the MOC compiler
|
||||
set(ProtoServer_QT_HEADERS
|
||||
${CURRENT_HEADER_DIR}/ProtoServer.h
|
||||
${CURRENT_SOURCE_DIR}/ProtoClientConnection.h
|
||||
)
|
||||
|
||||
set(ProtoServer_HEADERS
|
||||
)
|
||||
|
||||
set(ProtoServer_SOURCES
|
||||
${CURRENT_SOURCE_DIR}/ProtoServer.cpp
|
||||
${CURRENT_SOURCE_DIR}/ProtoClientConnection.cpp
|
||||
)
|
||||
|
||||
set(ProtoServer_PROTOS
|
||||
${CURRENT_SOURCE_DIR}/message.proto
|
||||
)
|
||||
|
||||
protobuf_generate_cpp(ProtoServer_PROTO_SRCS ProtoServer_PROTO_HDRS
|
||||
${ProtoServer_PROTOS}
|
||||
)
|
||||
|
||||
qt4_wrap_cpp(ProtoServer_HEADERS_MOC ${ProtoServer_QT_HEADERS})
|
||||
|
||||
add_library(protoserver
|
||||
${ProtoServer_HEADERS}
|
||||
${ProtoServer_QT_HEADERS}
|
||||
${ProtoServer_SOURCES}
|
||||
${ProtoServer_HEADERS_MOC}
|
||||
${ProtoServer_PROTOS}
|
||||
${ProtoServer_PROTO_SRCS}
|
||||
${ProtoServer_PROTO_HDRS}
|
||||
)
|
||||
|
||||
target_link_libraries(protoserver
|
||||
hyperion
|
||||
hyperion-utils
|
||||
${PROTOBUF_LIBRARIES})
|
||||
|
||||
qt4_use_modules(protoserver
|
||||
Core
|
||||
Gui
|
||||
Network)
|
223
libsrc/protoserver/ProtoClientConnection.cpp
Normal file
223
libsrc/protoserver/ProtoClientConnection.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
// system includes
|
||||
#include <stdexcept>
|
||||
#include <cassert>
|
||||
|
||||
// stl includes
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iterator>
|
||||
|
||||
// Qt includes
|
||||
#include <QRgb>
|
||||
#include <QResource>
|
||||
#include <QDateTime>
|
||||
|
||||
// hyperion util includes
|
||||
#include "hyperion/ImageProcessorFactory.h"
|
||||
#include "hyperion/ImageProcessor.h"
|
||||
#include "utils/RgbColor.h"
|
||||
|
||||
// project includes
|
||||
#include "ProtoClientConnection.h"
|
||||
|
||||
ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion) :
|
||||
QObject(),
|
||||
_socket(socket),
|
||||
_imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()),
|
||||
_hyperion(hyperion),
|
||||
_receiveBuffer()
|
||||
{
|
||||
// connect internal signals and slots
|
||||
connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
|
||||
connect(_socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
||||
}
|
||||
|
||||
ProtoClientConnection::~ProtoClientConnection()
|
||||
{
|
||||
delete _socket;
|
||||
}
|
||||
|
||||
void ProtoClientConnection::readData()
|
||||
{
|
||||
_receiveBuffer += _socket->readAll();
|
||||
|
||||
// check if we can read a message size
|
||||
if (_receiveBuffer.size() <= 4)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// read the message size
|
||||
uint32_t messageSize =
|
||||
((_receiveBuffer[0]<<24) & 0xFF000000) |
|
||||
((_receiveBuffer[1]<<16) & 0x00FF0000) |
|
||||
((_receiveBuffer[2]<< 8) & 0x0000FF00) |
|
||||
((_receiveBuffer[3] ) & 0x000000FF);
|
||||
|
||||
// check if we can read a complete message
|
||||
if ((uint32_t) _receiveBuffer.size() < messageSize + 4)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// read a message
|
||||
proto::HyperionRequest message;
|
||||
if (!message.ParseFromArray(_receiveBuffer.data() + 4, messageSize))
|
||||
{
|
||||
sendErrorReply("Unable to parse message");
|
||||
}
|
||||
|
||||
// handle the message
|
||||
handleMessage(message);
|
||||
|
||||
// remove message data from buffer
|
||||
_receiveBuffer = _receiveBuffer.mid(messageSize + 4);
|
||||
}
|
||||
|
||||
void ProtoClientConnection::socketClosed()
|
||||
{
|
||||
emit connectionClosed(this);
|
||||
}
|
||||
|
||||
void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message)
|
||||
{
|
||||
switch (message.command())
|
||||
{
|
||||
case proto::HyperionRequest::COLOR:
|
||||
if (!message.HasExtension(proto::ColorRequest::colorRequest))
|
||||
{
|
||||
sendErrorReply("Received COLOR command without ColorRequest");
|
||||
break;
|
||||
}
|
||||
handleColorCommand(message.GetExtension(proto::ColorRequest::colorRequest));
|
||||
break;
|
||||
case proto::HyperionRequest::IMAGE:
|
||||
if (!message.HasExtension(proto::ImageRequest::imageRequest))
|
||||
{
|
||||
sendErrorReply("Received IMAGE command without ImageRequest");
|
||||
break;
|
||||
}
|
||||
handleImageCommand(message.GetExtension(proto::ImageRequest::imageRequest));
|
||||
break;
|
||||
case proto::HyperionRequest::CLEAR:
|
||||
if (!message.HasExtension(proto::ClearRequest::clearRequest))
|
||||
{
|
||||
sendErrorReply("Received CLEAR command without ClearRequest");
|
||||
break;
|
||||
}
|
||||
handleClearCommand(message.GetExtension(proto::ClearRequest::clearRequest));
|
||||
break;
|
||||
case proto::HyperionRequest::CLEARALL:
|
||||
handleClearallCommand();
|
||||
break;
|
||||
default:
|
||||
handleNotImplemented();
|
||||
}
|
||||
}
|
||||
|
||||
void ProtoClientConnection::handleColorCommand(const proto::ColorRequest &message)
|
||||
{
|
||||
// extract parameters
|
||||
int priority = message.priority();
|
||||
int duration = message.has_duration() ? message.duration() : -1;
|
||||
RgbColor color;
|
||||
color.red = qRed(message.rgbcolor());
|
||||
color.green = qGreen(message.rgbcolor());
|
||||
color.blue = qBlue(message.rgbcolor());
|
||||
|
||||
// set output
|
||||
_hyperion->setColor(priority, color, duration);
|
||||
|
||||
// send reply
|
||||
sendSuccessReply();
|
||||
}
|
||||
|
||||
void ProtoClientConnection::handleImageCommand(const proto::ImageRequest &message)
|
||||
{
|
||||
// extract parameters
|
||||
int priority = message.priority();
|
||||
int duration = message.has_duration() ? message.duration() : -1;
|
||||
int width = message.imagewidth();
|
||||
int height = message.imageheight();
|
||||
const std::string & imageData = message.imagedata();
|
||||
|
||||
// check consistency of the size of the received data
|
||||
if ((int) imageData.size() != width*height*3)
|
||||
{
|
||||
sendErrorReply("Size of image data does not match with the width and height");
|
||||
return;
|
||||
}
|
||||
|
||||
// set width and height of the image processor
|
||||
_imageProcessor->setSize(width, height);
|
||||
|
||||
// create RgbImage
|
||||
RgbImage image(width, height);
|
||||
memcpy(image.memptr(), imageData.c_str(), imageData.size());
|
||||
|
||||
// process the image
|
||||
std::vector<RgbColor> ledColors = _imageProcessor->process(image);
|
||||
_hyperion->setColors(priority, ledColors, duration);
|
||||
|
||||
// send reply
|
||||
sendSuccessReply();
|
||||
}
|
||||
|
||||
|
||||
void ProtoClientConnection::handleClearCommand(const proto::ClearRequest &message)
|
||||
{
|
||||
// extract parameters
|
||||
int priority = message.priority();
|
||||
|
||||
// clear priority
|
||||
_hyperion->clear(priority);
|
||||
|
||||
// send reply
|
||||
sendSuccessReply();
|
||||
}
|
||||
|
||||
void ProtoClientConnection::handleClearallCommand()
|
||||
{
|
||||
// clear priority
|
||||
_hyperion->clearall();
|
||||
|
||||
// send reply
|
||||
sendSuccessReply();
|
||||
}
|
||||
|
||||
|
||||
void ProtoClientConnection::handleNotImplemented()
|
||||
{
|
||||
sendErrorReply("Command not implemented");
|
||||
}
|
||||
|
||||
void ProtoClientConnection::sendMessage(const google::protobuf::Message &message)
|
||||
{
|
||||
std::string serializedReply = message.SerializeAsString();
|
||||
uint32_t size = serializedReply.size();
|
||||
uint8_t sizeData[] = {uint8_t(size >> 24), uint8_t(size >> 16), uint8_t(size >> 8), uint8_t(size)};
|
||||
_socket->write((const char *) sizeData, sizeof(sizeData));
|
||||
_socket->write(serializedReply.data(), serializedReply.length());
|
||||
_socket->flush();
|
||||
}
|
||||
|
||||
void ProtoClientConnection::sendSuccessReply()
|
||||
{
|
||||
// create reply
|
||||
proto::HyperionReply reply;
|
||||
reply.set_success(true);
|
||||
|
||||
// send reply
|
||||
sendMessage(reply);
|
||||
}
|
||||
|
||||
void ProtoClientConnection::sendErrorReply(const std::string &error)
|
||||
{
|
||||
// create reply
|
||||
proto::HyperionReply reply;
|
||||
reply.set_success(false);
|
||||
reply.set_error(error);
|
||||
|
||||
// send reply
|
||||
sendMessage(reply);
|
||||
}
|
126
libsrc/protoserver/ProtoClientConnection.h
Normal file
126
libsrc/protoserver/ProtoClientConnection.h
Normal file
@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
|
||||
// stl includes
|
||||
#include <string>
|
||||
|
||||
// Qt includes
|
||||
#include <QByteArray>
|
||||
#include <QTcpSocket>
|
||||
|
||||
// Hyperion includes
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
// proto includes
|
||||
#include "message.pb.h"
|
||||
|
||||
class ImageProcessor;
|
||||
|
||||
///
|
||||
/// The Connection object created by \a ProtoServer when a new connection is establshed
|
||||
///
|
||||
class ProtoClientConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
///
|
||||
/// Constructor
|
||||
/// @param socket The Socket object for this connection
|
||||
/// @param hyperion The Hyperion server
|
||||
///
|
||||
ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion);
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
~ProtoClientConnection();
|
||||
|
||||
signals:
|
||||
///
|
||||
/// Signal which is emitted when the connection is being closed
|
||||
/// @param connection This connection object
|
||||
///
|
||||
void connectionClosed(ProtoClientConnection * connection);
|
||||
|
||||
private slots:
|
||||
///
|
||||
/// Slot called when new data has arrived
|
||||
///
|
||||
void readData();
|
||||
|
||||
///
|
||||
/// Slot called when this connection is being closed
|
||||
///
|
||||
void socketClosed();
|
||||
|
||||
private:
|
||||
///
|
||||
/// Handle an incoming Proto message
|
||||
///
|
||||
/// @param message the incoming message as string
|
||||
///
|
||||
void handleMessage(const proto::HyperionRequest &message);
|
||||
|
||||
///
|
||||
/// Handle an incoming Proto Color message
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
void handleColorCommand(const proto::ColorRequest & message);
|
||||
|
||||
///
|
||||
/// Handle an incoming Proto Image message
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
void handleImageCommand(const proto::ImageRequest & message);
|
||||
|
||||
///
|
||||
/// Handle an incoming Proto Clear message
|
||||
///
|
||||
/// @param message the incoming message
|
||||
///
|
||||
void handleClearCommand(const proto::ClearRequest & message);
|
||||
|
||||
///
|
||||
/// Handle an incoming Proto Clearall message
|
||||
///
|
||||
void handleClearallCommand();
|
||||
|
||||
///
|
||||
/// Handle an incoming Proto message of unknown type
|
||||
///
|
||||
void handleNotImplemented();
|
||||
|
||||
///
|
||||
/// Send a message to the connected client
|
||||
///
|
||||
/// @param message The Proto message to send
|
||||
///
|
||||
void sendMessage(const google::protobuf::Message &message);
|
||||
|
||||
///
|
||||
/// Send a standard reply indicating success
|
||||
///
|
||||
void sendSuccessReply();
|
||||
|
||||
///
|
||||
/// Send an error message back to the client
|
||||
///
|
||||
/// @param error String describing the error
|
||||
///
|
||||
void sendErrorReply(const std::string & error);
|
||||
|
||||
private:
|
||||
/// The TCP-Socket that is connected tot the Proto-client
|
||||
QTcpSocket * _socket;
|
||||
|
||||
/// The processor for translating images to led-values
|
||||
ImageProcessor * _imageProcessor;
|
||||
|
||||
/// Link to Hyperion for writing led-values to a priority channel
|
||||
Hyperion * _hyperion;
|
||||
|
||||
/// The buffer used for reading data from the socket
|
||||
QByteArray _receiveBuffer;
|
||||
};
|
57
libsrc/protoserver/ProtoServer.cpp
Normal file
57
libsrc/protoserver/ProtoServer.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
// system includes
|
||||
#include <stdexcept>
|
||||
|
||||
// project includes
|
||||
#include <protoserver/ProtoServer.h>
|
||||
#include "ProtoClientConnection.h"
|
||||
|
||||
ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port) :
|
||||
QObject(),
|
||||
_hyperion(hyperion),
|
||||
_server(),
|
||||
_openConnections()
|
||||
{
|
||||
if (!_server.listen(QHostAddress::Any, port))
|
||||
{
|
||||
throw std::runtime_error("Proto server could not bind to port");
|
||||
}
|
||||
|
||||
// Set trigger for incoming connections
|
||||
connect(&_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
|
||||
}
|
||||
|
||||
ProtoServer::~ProtoServer()
|
||||
{
|
||||
foreach (ProtoClientConnection * connection, _openConnections) {
|
||||
delete connection;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ProtoServer::getPort() const
|
||||
{
|
||||
return _server.serverPort();
|
||||
}
|
||||
|
||||
void ProtoServer::newConnection()
|
||||
{
|
||||
QTcpSocket * socket = _server.nextPendingConnection();
|
||||
|
||||
if (socket != nullptr)
|
||||
{
|
||||
std::cout << "New proto connection" << std::endl;
|
||||
ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion);
|
||||
_openConnections.insert(connection);
|
||||
|
||||
// register slot for cleaning up after the connection closed
|
||||
connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*)));
|
||||
}
|
||||
}
|
||||
|
||||
void ProtoServer::closedConnection(ProtoClientConnection *connection)
|
||||
{
|
||||
std::cout << "Proto connection closed" << std::endl;
|
||||
_openConnections.remove(connection);
|
||||
|
||||
// schedule to delete the connection object
|
||||
connection->deleteLater();
|
||||
}
|
69
libsrc/protoserver/message.proto
Normal file
69
libsrc/protoserver/message.proto
Normal file
@ -0,0 +1,69 @@
|
||||
package proto;
|
||||
|
||||
message HyperionRequest {
|
||||
enum Command {
|
||||
COLOR = 1;
|
||||
IMAGE = 2;
|
||||
CLEAR = 3;
|
||||
CLEARALL = 4;
|
||||
}
|
||||
|
||||
// command specification
|
||||
required Command command = 1;
|
||||
|
||||
// extensions to define all specific requests
|
||||
extensions 10 to 100;
|
||||
}
|
||||
|
||||
message ColorRequest {
|
||||
extend HyperionRequest {
|
||||
required ColorRequest colorRequest = 10;
|
||||
}
|
||||
|
||||
// priority to use when setting the color
|
||||
required int32 priority = 1;
|
||||
|
||||
// integer value containing the rgb color (0x00RRGGBB)
|
||||
required int32 rgbColor = 2;
|
||||
|
||||
// duration of the request (negative results in infinite)
|
||||
optional int32 duration = 3;
|
||||
}
|
||||
|
||||
message ImageRequest {
|
||||
extend HyperionRequest {
|
||||
required ImageRequest imageRequest = 11;
|
||||
}
|
||||
|
||||
// priority to use when setting the image
|
||||
required int32 priority = 1;
|
||||
|
||||
// width of the image
|
||||
required int32 imagewidth = 2;
|
||||
|
||||
// height of the image
|
||||
required int32 imageheight = 3;
|
||||
|
||||
// image data
|
||||
required bytes imagedata = 4;
|
||||
|
||||
// duration of the request (negative results in infinite)
|
||||
optional int32 duration = 5;
|
||||
}
|
||||
|
||||
message ClearRequest {
|
||||
extend HyperionRequest {
|
||||
required ClearRequest clearRequest = 12;
|
||||
}
|
||||
|
||||
// priority which need to be cleared
|
||||
required int32 priority = 1;
|
||||
}
|
||||
|
||||
message HyperionReply {
|
||||
// flag indication success or failure
|
||||
required bool success = 1;
|
||||
|
||||
// string indicating the reason for failure (if applicable)
|
||||
optional string error = 2;
|
||||
}
|
@ -45,8 +45,6 @@ void HsvTransform::transform(uint8_t & red, uint8_t & green, uint8_t & blue) con
|
||||
uint8_t saturation, value;
|
||||
rgb2hsv(red, green, blue, hue, saturation, value);
|
||||
|
||||
std::cout << int(hue) << " " << int(saturation) << " " << int(value) << std::endl;
|
||||
|
||||
int s = saturation * _saturationGain;
|
||||
if (s > 255)
|
||||
saturation = 255;
|
||||
|
@ -7,7 +7,7 @@ XBMCVideoChecker::XBMCVideoChecker(const std::string & address, uint16_t port, u
|
||||
QObject(),
|
||||
_address(QString::fromStdString(address)),
|
||||
_port(port),
|
||||
_request("{\"jsonrpc\":\"2.0\",\"method\":\"Player.GetActivePlayers\",\"id\":666}"),
|
||||
_request(R"({"jsonrpc":"2.0","method":"Player.GetActivePlayers","id":666})"),
|
||||
_timer(),
|
||||
_socket(),
|
||||
_grabVideo(grabVideo),
|
||||
|
@ -44,7 +44,7 @@ public class MiscConfigPanel extends JPanel {
|
||||
add(mMenuLabel);
|
||||
|
||||
mMenuCombo = new JComboBox<>(new String[] {"On", "Off"});
|
||||
mMenuCombo.setSelectedItem("Off");
|
||||
mMenuCombo.setSelectedItem(mMiscConfig.mMenuOn? "On": "Off");
|
||||
mMenuCombo.setToolTipText("Enables('On') or disbales('Off') the ambi-light in the XBMC Menu");
|
||||
mMenuCombo.addActionListener(mActionListener);
|
||||
add(mMenuCombo);
|
||||
@ -53,7 +53,7 @@ public class MiscConfigPanel extends JPanel {
|
||||
add(mVideoLabel);
|
||||
|
||||
mVideoCombo = new JComboBox<>(new String[] {"On", "Off"});
|
||||
mVideoCombo.setSelectedItem("On");
|
||||
mVideoCombo.setSelectedItem(mMiscConfig.mVideoOn? "On": "Off");
|
||||
mVideoCombo.setToolTipText("Enables('On') or disbales('Off') the ambi-light during video playback");
|
||||
mVideoCombo.addActionListener(mActionListener);
|
||||
add(mVideoCombo);
|
||||
@ -62,7 +62,7 @@ public class MiscConfigPanel extends JPanel {
|
||||
add(mPictureLabel);
|
||||
|
||||
mPictureCombo = new JComboBox<>(new String[] {"On", "Off"});
|
||||
mPictureCombo.setSelectedItem("Off");
|
||||
mPictureCombo.setSelectedItem(mMiscConfig.mPictureOn? "On": "Off");
|
||||
mPictureCombo.setToolTipText("Enables('On') or disbales('Off') the ambi-light when viewing pictures");
|
||||
mPictureCombo.addActionListener(mActionListener);
|
||||
add(mPictureCombo);
|
||||
@ -71,7 +71,7 @@ public class MiscConfigPanel extends JPanel {
|
||||
add(mAudioLabel);
|
||||
|
||||
mAudioCombo = new JComboBox<>(new String[] {"On", "Off"});
|
||||
mAudioCombo.setSelectedItem("Off");
|
||||
mAudioCombo.setSelectedItem(mMiscConfig.mAudioOn? "On": "Off");
|
||||
mAudioCombo.setToolTipText("Enables('On') or disbales('Off') the ambi-light when listing to audio");
|
||||
mAudioCombo.addActionListener(mActionListener);
|
||||
add(mAudioCombo);
|
||||
|
@ -1 +1 @@
|
||||
176f5c8e4a406929620764b19e77c5120570325c
|
||||
d37be0ef34a74fb15c9ec81e9ebadb57de62d294
|
@ -1 +1 @@
|
||||
048b062d931b7754a533734a1dec21692bce2dc6
|
||||
1df18121f930623884da3de93f146f93d11f621c
|
@ -1 +1 @@
|
||||
bd23dc9ed11283d527effc78e437e8ef18903123
|
||||
97019f8cd170a7792bb81ae09efd690669eef567
|
@ -1 +1 @@
|
||||
427d6ffe9935a3011f05b13bcf44a47796e99a80
|
||||
b607e73b98996bfa40d19d508be01919552552d0
|
@ -1 +1 @@
|
||||
0dd04b5ec932aa251136740c6ea87f71847eb537
|
||||
0d3aafb4a85649e53888a660b87de98f59f0ec32
|
@ -1 +1 @@
|
||||
10fa576b5a494b9e0377e8b944904bfa7ac97cb6
|
||||
7962c1194cb2a2b7af6c3b34151701e113f00087
|
@ -1 +1 @@
|
||||
620cf4f8a4c8dc62cabe9045c1ad04c38cecb942
|
||||
ad1aba652ea186845d0c340cbeca7efb9d662e10
|
@ -10,30 +10,30 @@ public class ColorConfig {
|
||||
/** The saturation gain (in HSV space) */
|
||||
double mSaturationGain = 1.0;
|
||||
/** The value gain (in HSV space) */
|
||||
double mValueGain = 1.0;
|
||||
double mValueGain = 1.5;
|
||||
|
||||
/** The minimum required RED-value (in RGB space) */
|
||||
double mRedThreshold = 0.0;
|
||||
double mRedThreshold = 0.1;
|
||||
/** The gamma-curve correct for the RED-value (in RGB space) */
|
||||
double mRedGamma = 1.0;
|
||||
double mRedGamma = 2.0;
|
||||
/** The black-level of the RED-value (in RGB space) */
|
||||
double mRedBlacklevel = 0.0;
|
||||
/** The white-level of the RED-value (in RGB space) */
|
||||
double mRedWhitelevel = 1.0;
|
||||
double mRedWhitelevel = 0.8;
|
||||
|
||||
/** The minimum required GREEN-value (in RGB space) */
|
||||
double mGreenThreshold = 0.0;
|
||||
double mGreenThreshold = 0.1;
|
||||
/** The gamma-curve correct for the GREEN-value (in RGB space) */
|
||||
double mGreenGamma = 1.0;
|
||||
double mGreenGamma = 2.0;
|
||||
/** The black-level of the GREEN-value (in RGB space) */
|
||||
double mGreenBlacklevel = 0.0;
|
||||
/** The white-level of the GREEN-value (in RGB space) */
|
||||
double mGreenWhitelevel = 1.0;
|
||||
|
||||
/** The minimum required BLUE-value (in RGB space) */
|
||||
double mBlueThreshold = 0.0;
|
||||
double mBlueThreshold = 0.1;
|
||||
/** The gamma-curve correct for the BLUE-value (in RGB space) */
|
||||
double mBlueGamma = 1.0;
|
||||
double mBlueGamma = 2.0;
|
||||
/** The black-level of the BLUE-value (in RGB space) */
|
||||
double mBlueBlacklevel = 0.0;
|
||||
/** The white-level of the BLUE-value (in RGB space) */
|
||||
@ -75,8 +75,8 @@ public class ColorConfig {
|
||||
StringBuffer strBuf = new StringBuffer();
|
||||
strBuf.append("\t\t\"hsv\" :\n");
|
||||
strBuf.append("\t\t{\n");
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tsaturationGain : %.4f,\n", mSaturationGain));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tvaluGain : %.4f\n", mValueGain));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"saturationGain\" : %.4f,\n", mSaturationGain));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"valuGain\" : %.4f\n", mValueGain));
|
||||
|
||||
strBuf.append("\t\t}");
|
||||
return strBuf.toString();
|
||||
@ -92,26 +92,26 @@ public class ColorConfig {
|
||||
|
||||
strBuf.append("\t\t\"red\" :\n");
|
||||
strBuf.append("\t\t{\n");
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tthreshold : %.4f,\n", mRedThreshold));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tgamma : %.4f,\n", mRedGamma));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tblacklevel : %.4f,\n", mRedBlacklevel));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\twhitelevel : %.4f\n", mRedWhitelevel));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"threshold\" : %.4f,\n", mRedThreshold));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"gamma\" : %.4f,\n", mRedGamma));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"blacklevel\" : %.4f,\n", mRedBlacklevel));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"whitelevel\" : %.4f\n", mRedWhitelevel));
|
||||
strBuf.append("\t\t},\n");
|
||||
|
||||
strBuf.append("\t\t\"green\" :\n");
|
||||
strBuf.append("\t\t{\n");
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tthreshold : %.4f,\n", mGreenThreshold));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tgamma : %.4f,\n", mGreenGamma));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tblacklevel : %.4f,\n", mGreenBlacklevel));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\twhitelevel : %.4f\n", mGreenWhitelevel));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"threshold\" : %.4f,\n", mGreenThreshold));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"gamma\" : %.4f,\n", mGreenGamma));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"blacklevel\" : %.4f,\n", mGreenBlacklevel));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"whitelevel\" : %.4f\n", mGreenWhitelevel));
|
||||
strBuf.append("\t\t},\n");
|
||||
|
||||
strBuf.append("\t\t\"blue\" :\n");
|
||||
strBuf.append("\t\t{\n");
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tthreshold : %.4f,\n", mBlueThreshold));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tgamma : %.4f,\n", mBlueGamma));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\tblacklevel : %.4f,\n", mBlueBlacklevel));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\twhitelevel : %.4f\n", mBlueWhitelevel));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"threshold\" : %.4f,\n", mBlueThreshold));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"gamma\" : %.4f,\n", mBlueGamma));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"blacklevel\" : %.4f,\n", mBlueBlacklevel));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\t\"whitelevel\" : %.4f\n", mBlueWhitelevel));
|
||||
strBuf.append("\t\t}");
|
||||
|
||||
return strBuf.toString();
|
||||
|
@ -12,7 +12,7 @@ public class DeviceConfig {
|
||||
/** The device 'file' name */
|
||||
String mOutput = "/dev/spidev0.0";
|
||||
/** The baudrate of the device */
|
||||
int mBaudrate = 48000;
|
||||
int mBaudrate = 1000000;
|
||||
|
||||
/**
|
||||
* Creates the JSON string of the configuration as used in the Hyperion daemon configfile
|
||||
|
@ -18,8 +18,6 @@ public class MiscConfig {
|
||||
/** The interval of frame grabs (screen shots) [ms] */
|
||||
public int mFrameGrabberInterval_ms = 100;
|
||||
|
||||
/** Flag enabling/disabling XBMC communication */
|
||||
public boolean mXbmcChecker = true;
|
||||
/** The IP-address of XBMC */
|
||||
public String mXbmcAddress = "127.0.0.1";
|
||||
/** The TCP JSON-Port of XBMC */
|
||||
@ -29,9 +27,15 @@ public class MiscConfig {
|
||||
/** Flag indicating that the frame-grabber is on during XBMC menu */
|
||||
public boolean mMenuOn = false;
|
||||
/** Flag indicating that the frame-grabber is on during picture slideshow */
|
||||
public boolean mPictureOn = false;
|
||||
public boolean mPictureOn = true;
|
||||
/** Flag indicating that the frame-grabber is on during audio playback */
|
||||
public boolean mAudioOn = false;
|
||||
public boolean mAudioOn = true;
|
||||
|
||||
/** The TCP port at which the JSON server is listening for incoming connections */
|
||||
public int mJsonPort = 19444;
|
||||
|
||||
/** The TCP port at which the Protobuf server is listening for incoming connections */
|
||||
public int mProtoPort = 19445;
|
||||
|
||||
/**
|
||||
* Creates the JSON string of the configuration as used in the Hyperion daemon configfile
|
||||
@ -41,26 +45,6 @@ public class MiscConfig {
|
||||
public String toJsonString() {
|
||||
StringBuffer strBuf = new StringBuffer();
|
||||
|
||||
strBuf.append("\t/// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: \n");
|
||||
strBuf.append("\t/// * enable : Flag for enabling or disabling the XBMC-based frame grabbing\n");
|
||||
strBuf.append("\t/// * xbmcAddress : The IP address of the XBMC-host\n");
|
||||
strBuf.append("\t/// * xbmcTcpPort : The TCP-port of the XBMC-server\n");
|
||||
strBuf.append("\t/// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback\n");
|
||||
strBuf.append("\t/// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show\n");
|
||||
strBuf.append("\t/// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback\n");
|
||||
strBuf.append("\t/// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu\n");
|
||||
|
||||
strBuf.append("\t\"xbmcVideoChecker\" :\n");
|
||||
strBuf.append("\t{\n");
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"enable\" : %s,\n", mXbmcChecker));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"xbmcAddress\" : \"%s\",\n", mXbmcAddress));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"xbmcTcpPort\" : %d,\n", mXbmcTcpPort));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"grabVideo\" : %s,\n", mVideoOn));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"grabPictures\" : %s,\n", mPictureOn));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"grabAudio\" : %s,\n", mAudioOn));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"grabMenu\" : %s\n", mMenuOn));
|
||||
strBuf.append("\t},\n");
|
||||
|
||||
strBuf.append("\t/// The boot-sequence configuration, contains the following items: \n");
|
||||
strBuf.append("\t/// * type : The type of the boot-sequence ('rainbow', 'knight_rider', 'none') \n");
|
||||
strBuf.append("\t/// * duration_ms : The length of the boot-sequence [ms]\n");
|
||||
@ -69,7 +53,7 @@ public class MiscConfig {
|
||||
strBuf.append("\t{\n");
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"type\" : \"%s\",\n", mBootSequence));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"duration_ms\" : %d\n", mBootSequenceLength_ms));
|
||||
strBuf.append("\t},\n");
|
||||
strBuf.append("\t},\n\n");
|
||||
|
||||
|
||||
strBuf.append("\t/// The configuration for the frame-grabber, contains the following items: \n");
|
||||
@ -82,10 +66,44 @@ public class MiscConfig {
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"width\" : %d,\n", mFrameGrabberWidth));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"height\" : %d,\n", mFrameGrabberHeight));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"frequency_Hz\" : %.1f\n", 1000.0/mFrameGrabberInterval_ms));
|
||||
strBuf.append("\t},\n\n");
|
||||
|
||||
|
||||
strBuf.append("\t/// The configuration of the XBMC connection used to enable and disable the frame-grabber. Contains the following fields: \n");
|
||||
strBuf.append("\t/// * xbmcAddress : The IP address of the XBMC-host\n");
|
||||
strBuf.append("\t/// * xbmcTcpPort : The TCP-port of the XBMC-server\n");
|
||||
strBuf.append("\t/// * grabVideo : Flag indicating that the frame-grabber is on(true) during video playback\n");
|
||||
strBuf.append("\t/// * grabPictures : Flag indicating that the frame-grabber is on(true) during picture show\n");
|
||||
strBuf.append("\t/// * grabAudio : Flag indicating that the frame-grabber is on(true) during audio playback\n");
|
||||
strBuf.append("\t/// * grabMenu : Flag indicating that the frame-grabber is on(true) in the XBMC menu\n");
|
||||
|
||||
strBuf.append("\t\"xbmcVideoChecker\" :\n");
|
||||
strBuf.append("\t{\n");
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"xbmcAddress\" : \"%s\",\n", mXbmcAddress));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"xbmcTcpPort\" : %d,\n", mXbmcTcpPort));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"grabVideo\" : %s,\n", mVideoOn));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"grabPictures\" : %s,\n", mPictureOn));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"grabAudio\" : %s,\n", mAudioOn));
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"grabMenu\" : %s\n", mMenuOn));
|
||||
strBuf.append("\t},\n\n");
|
||||
|
||||
|
||||
strBuf.append("\t/// The configuration of the Json server which enables the json remote interface\n");
|
||||
strBuf.append("\t/// * port : Port at which the json server is started\n");
|
||||
strBuf.append("\t\"jsonServer\" :\n");
|
||||
strBuf.append("\t{\n");
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"port\" : %d\n", mJsonPort));
|
||||
strBuf.append("\t},\n\n");
|
||||
|
||||
|
||||
strBuf.append("\t/// The configuration of the Proto server which enables the protobuffer remote interface\n");
|
||||
strBuf.append("\t/// * port : Port at which the protobuffer server is started\n");
|
||||
|
||||
strBuf.append("\t\"protoServer\" :\n");
|
||||
strBuf.append("\t{\n");
|
||||
strBuf.append(String.format(Locale.ROOT, "\t\t\"port\" : %d\n", mProtoPort));
|
||||
strBuf.append("\t}");
|
||||
|
||||
return strBuf.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -7,4 +7,5 @@ target_link_libraries(hyperiond
|
||||
hyperion
|
||||
dispmanx-grabber
|
||||
xbmcvideochecker
|
||||
jsonserver)
|
||||
jsonserver
|
||||
protoserver)
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
// C++ includes
|
||||
#include <csignal>
|
||||
|
||||
@ -24,6 +23,9 @@
|
||||
// JsonServer includes
|
||||
#include <jsonserver/JsonServer.h>
|
||||
|
||||
// ProtoServer includes
|
||||
#include <protoserver/ProtoServer.h>
|
||||
|
||||
void signal_handler(const int signum)
|
||||
{
|
||||
QCoreApplication::quit();
|
||||
@ -66,7 +68,7 @@ int main(int argc, char** argv)
|
||||
{
|
||||
std::cout << "Missing required configuration file. Usage:" << std::endl;
|
||||
std::cout << "hyperiond [config.file]" << std::endl;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const std::string configFile = argv[1];
|
||||
@ -76,14 +78,24 @@ int main(int argc, char** argv)
|
||||
Hyperion hyperion(config);
|
||||
std::cout << "Hyperion created and initialised" << std::endl;
|
||||
|
||||
BootSequence * bootSequence = BootSequenceFactory::createBootSequence(&hyperion, config["bootsequence"]);
|
||||
if (bootSequence)
|
||||
// create boot sequence if the configuration is present
|
||||
BootSequence * bootSequence = nullptr;
|
||||
if (config.isMember("bootsequence"))
|
||||
{
|
||||
bootSequence = BootSequenceFactory::createBootSequence(&hyperion, config["bootsequence"]);
|
||||
|
||||
if (bootSequence != nullptr)
|
||||
{
|
||||
bootSequence->start();
|
||||
}
|
||||
}
|
||||
|
||||
// create XBMC video checker if the configuration is present
|
||||
XBMCVideoChecker * xbmcVideoChecker = nullptr;
|
||||
if (config.isMember("xbmcVideoChecker"))
|
||||
{
|
||||
const Json::Value & videoCheckerConfig = config["xbmcVideoChecker"];
|
||||
XBMCVideoChecker xbmcVideoChecker(
|
||||
xbmcVideoChecker = new XBMCVideoChecker(
|
||||
videoCheckerConfig["xbmcAddress"].asString(),
|
||||
videoCheckerConfig["xbmcTcpPort"].asUInt(),
|
||||
1000,
|
||||
@ -91,38 +103,67 @@ int main(int argc, char** argv)
|
||||
videoCheckerConfig["grabPictures"].asBool(),
|
||||
videoCheckerConfig["grabAudio"].asBool(),
|
||||
videoCheckerConfig["grabMenu"].asBool());
|
||||
if (videoCheckerConfig["enable"].asBool())
|
||||
{
|
||||
xbmcVideoChecker.start();
|
||||
|
||||
xbmcVideoChecker->start();
|
||||
std::cout << "XBMC video checker created and started" << std::endl;
|
||||
}
|
||||
|
||||
// Construct and start the frame-grabber
|
||||
// Construct and start the frame-grabber if the configuration is present
|
||||
DispmanxWrapper * dispmanx = nullptr;
|
||||
if (config.isMember("framegrabber"))
|
||||
{
|
||||
const Json::Value & frameGrabberConfig = config["framegrabber"];
|
||||
DispmanxWrapper dispmanx(
|
||||
dispmanx = new DispmanxWrapper(
|
||||
frameGrabberConfig["width"].asUInt(),
|
||||
frameGrabberConfig["height"].asUInt(),
|
||||
frameGrabberConfig["frequency_Hz"].asUInt(),
|
||||
&hyperion);
|
||||
QObject::connect(&xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), &dispmanx, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
dispmanx.start();
|
||||
std::cout << "Frame grabber created and started" << std::endl;
|
||||
|
||||
JsonServer jsonServer(&hyperion);
|
||||
std::cout << "Json server created and started on port " << jsonServer.getPort() << std::endl;
|
||||
if (xbmcVideoChecker != nullptr)
|
||||
{
|
||||
QObject::connect(xbmcVideoChecker, SIGNAL(grabbingMode(GrabbingMode)), dispmanx, SLOT(setGrabbingMode(GrabbingMode)));
|
||||
}
|
||||
else
|
||||
{
|
||||
dispmanx->setGrabbingMode(GRABBINGMODE_VIDEO);
|
||||
}
|
||||
|
||||
dispmanx->start();
|
||||
std::cout << "Frame grabber created and started" << std::endl;
|
||||
}
|
||||
|
||||
// Create Json server if configuration is present
|
||||
JsonServer * jsonServer = nullptr;
|
||||
if (config.isMember("jsonServer"))
|
||||
{
|
||||
const Json::Value & jsonServerConfig = config["jsonServer"];
|
||||
jsonServer = new JsonServer(&hyperion, jsonServerConfig["port"].asUInt());
|
||||
std::cout << "Json server created and started on port " << jsonServer->getPort() << std::endl;
|
||||
}
|
||||
|
||||
// Create Proto server if configuration is present
|
||||
ProtoServer * protoServer = nullptr;
|
||||
if (config.isMember("protoServer"))
|
||||
{
|
||||
const Json::Value & protoServerConfig = config["protoServer"];
|
||||
protoServer = new ProtoServer(&hyperion, protoServerConfig["port"].asUInt());
|
||||
std::cout << "Proto server created and started on port " << protoServer->getPort() << std::endl;
|
||||
}
|
||||
|
||||
// run the application
|
||||
int rc = app.exec();
|
||||
std::cout << "Application closed" << std::endl;
|
||||
|
||||
// Stop the frame grabber
|
||||
dispmanx.stop();
|
||||
|
||||
// Delete the boot sequence
|
||||
delete bootSequence;
|
||||
|
||||
// Clear all colors (switchting off all leds)
|
||||
hyperion.clearall();
|
||||
|
||||
// Delete all component
|
||||
delete bootSequence;
|
||||
delete dispmanx;
|
||||
delete xbmcVideoChecker;
|
||||
delete jsonServer;
|
||||
delete protoServer;
|
||||
|
||||
// leave application
|
||||
return rc;
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ add_executable(test_spi
|
||||
target_link_libraries(test_spi
|
||||
hyperion)
|
||||
|
||||
|
||||
add_executable(test_configfile
|
||||
TestConfigFile.cpp)
|
||||
target_link_libraries(test_configfile
|
||||
@ -39,3 +38,6 @@ add_executable(test_blackborderprocessor
|
||||
TestBlackBorderProcessor.cpp)
|
||||
target_link_libraries(test_blackborderprocessor
|
||||
hyperion)
|
||||
|
||||
add_executable(spidev_test spidev_test.c)
|
||||
add_executable(gpio2spi switchPinCtrl.c)
|
||||
|
210
test/spidev_test.c
Normal file
210
test/spidev_test.c
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
* SPI testing utility (using spidev driver)
|
||||
*
|
||||
* Copyright (c) 2007 MontaVista Software, Inc.
|
||||
* Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License.
|
||||
*
|
||||
* Cross-compile with cross-gcc -I/path/to/cross-kernel/include
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/spi/spidev.h>
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
static void pabort(const char *s)
|
||||
{
|
||||
perror(s);
|
||||
abort();
|
||||
}
|
||||
|
||||
static const char *device = "/dev/spidev0.0";
|
||||
static uint8_t mode;
|
||||
static uint8_t bits = 8;
|
||||
static uint32_t speed = 500000;
|
||||
static uint16_t delay;
|
||||
|
||||
static void transfer(int fd)
|
||||
{
|
||||
int ret;
|
||||
uint8_t tx[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,
|
||||
0xF0, 0x0D,
|
||||
};
|
||||
uint8_t rx[ARRAY_SIZE(tx)] = {0, };
|
||||
struct spi_ioc_transfer tr = {
|
||||
.tx_buf = (unsigned long)tx,
|
||||
.rx_buf = (unsigned long)rx,
|
||||
.len = ARRAY_SIZE(tx),
|
||||
.delay_usecs = delay,
|
||||
.speed_hz = speed,
|
||||
.bits_per_word = bits,
|
||||
};
|
||||
|
||||
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
|
||||
if (ret < 1)
|
||||
pabort("can't send spi message");
|
||||
|
||||
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
|
||||
if (!(ret % 6))
|
||||
puts("");
|
||||
printf("%.2X ", rx[ret]);
|
||||
}
|
||||
puts("");
|
||||
}
|
||||
|
||||
static void print_usage(const char *prog)
|
||||
{
|
||||
printf("Usage: %s [-DsbdlHOLC3]\n", prog);
|
||||
puts(" -D --device device to use (default /dev/spidev0.0)\n"
|
||||
" -s --speed max speed (Hz)\n"
|
||||
" -d --delay delay (usec)\n"
|
||||
" -b --bpw bits per word \n"
|
||||
" -l --loop loopback\n"
|
||||
" -H --cpha clock phase\n"
|
||||
" -O --cpol clock polarity\n"
|
||||
" -L --lsb least significant bit first\n"
|
||||
" -C --cs-high chip select active high\n"
|
||||
" -3 --3wire SI/SO signals shared\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void parse_opts(int argc, char *argv[])
|
||||
{
|
||||
while (1) {
|
||||
static const struct option lopts[] = {
|
||||
{ "device", 1, 0, 'D' },
|
||||
{ "speed", 1, 0, 's' },
|
||||
{ "delay", 1, 0, 'd' },
|
||||
{ "bpw", 1, 0, 'b' },
|
||||
{ "loop", 0, 0, 'l' },
|
||||
{ "cpha", 0, 0, 'H' },
|
||||
{ "cpol", 0, 0, 'O' },
|
||||
{ "lsb", 0, 0, 'L' },
|
||||
{ "cs-high", 0, 0, 'C' },
|
||||
{ "3wire", 0, 0, '3' },
|
||||
{ "no-cs", 0, 0, 'N' },
|
||||
{ "ready", 0, 0, 'R' },
|
||||
{ NULL, 0, 0, 0 },
|
||||
};
|
||||
int c;
|
||||
|
||||
c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
|
||||
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'D':
|
||||
device = optarg;
|
||||
break;
|
||||
case 's':
|
||||
speed = atoi(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
delay = atoi(optarg);
|
||||
break;
|
||||
case 'b':
|
||||
bits = atoi(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
mode |= SPI_LOOP;
|
||||
break;
|
||||
case 'H':
|
||||
mode |= SPI_CPHA;
|
||||
break;
|
||||
case 'O':
|
||||
mode |= SPI_CPOL;
|
||||
break;
|
||||
case 'L':
|
||||
mode |= SPI_LSB_FIRST;
|
||||
break;
|
||||
case 'C':
|
||||
mode |= SPI_CS_HIGH;
|
||||
break;
|
||||
case '3':
|
||||
mode |= SPI_3WIRE;
|
||||
break;
|
||||
case 'N':
|
||||
mode |= SPI_NO_CS;
|
||||
break;
|
||||
case 'R':
|
||||
mode |= SPI_READY;
|
||||
break;
|
||||
default:
|
||||
print_usage(argv[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ret = 0;
|
||||
int fd;
|
||||
|
||||
parse_opts(argc, argv);
|
||||
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0)
|
||||
pabort("can't open device");
|
||||
|
||||
/*
|
||||
* spi mode
|
||||
*/
|
||||
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
|
||||
if (ret == -1)
|
||||
pabort("can't set spi mode");
|
||||
|
||||
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
|
||||
if (ret == -1)
|
||||
pabort("can't get spi mode");
|
||||
|
||||
/*
|
||||
* bits per word
|
||||
*/
|
||||
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
|
||||
if (ret == -1)
|
||||
pabort("can't set bits per word");
|
||||
|
||||
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
|
||||
if (ret == -1)
|
||||
pabort("can't get bits per word");
|
||||
|
||||
/*
|
||||
* max speed hz
|
||||
*/
|
||||
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
|
||||
if (ret == -1)
|
||||
pabort("can't set max speed hz");
|
||||
|
||||
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
|
||||
if (ret == -1)
|
||||
pabort("can't get max speed hz");
|
||||
|
||||
printf("spi mode: %d\n", mode);
|
||||
printf("bits per word: %d\n", bits);
|
||||
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
|
||||
|
||||
transfer(fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
return ret;
|
||||
}
|
177
test/switchPinCtrl.c
Normal file
177
test/switchPinCtrl.c
Normal file
@ -0,0 +1,177 @@
|
||||
//
|
||||
// Simple byte wise SPI driver
|
||||
// Demo how to set up memmap and access SPI registers.
|
||||
// Code seems to be working but has not been much tested.
|
||||
// G.J. van Loo 15-Jan-2012
|
||||
//
|
||||
|
||||
|
||||
|
||||
// Access from ARM Running Linux
|
||||
|
||||
#define BCM2708_PERI_BASE 0x20000000
|
||||
#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */
|
||||
#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 */
|
||||
#define MCORE_BASE (BCM2708_PERI_BASE + 0x0000) /* Fake frame buffer device */
|
||||
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
|
||||
#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 controller */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#define PAGE_SIZE (4*1024)
|
||||
#define BLOCK_SIZE (4*1024)
|
||||
|
||||
int mem_fd;
|
||||
char *gpio_mem, *gpio_map;
|
||||
char *spi0_mem, *spi0_map;
|
||||
|
||||
|
||||
// I/O access
|
||||
volatile unsigned *gpio;
|
||||
volatile unsigned *spi0;
|
||||
|
||||
|
||||
// SPI operation
|
||||
|
||||
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
|
||||
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
|
||||
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
|
||||
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
|
||||
|
||||
//
|
||||
#define SPI0_CNTLSTAT *(spi0 + 0)
|
||||
#define SPI0_FIFO *(spi0 + 1)
|
||||
#define SPI0_CLKSPEED *(spi0 + 2)
|
||||
|
||||
// SPI0_CNTLSTAT register bits
|
||||
|
||||
#define SPI0_CS_CS2ACTHIGH 0x00800000 // CS2 active high
|
||||
#define SPI0_CS_CS1ACTHIGH 0x00400000 // CS1 active high
|
||||
#define SPI0_CS_CS0ACTHIGH 0x00200000 // CS0 active high
|
||||
#define SPI0_CS_RXFIFOFULL 0x00100000 // Receive FIFO full
|
||||
#define SPI0_CS_RXFIFO3_4 0x00080000 // Receive FIFO 3/4 full
|
||||
#define SPI0_CS_TXFIFOSPCE 0x00040000 // Transmit FIFO has space
|
||||
#define SPI0_CS_RXFIFODATA 0x00020000 // Receive FIFO has data
|
||||
#define SPI0_CS_DONE 0x00010000 // SPI transfer done. WRT to CLR!
|
||||
#define SPI0_CS_MOSI_INPUT 0x00001000 // MOSI is input, read from MOSI (BI-dir mode)
|
||||
#define SPI0_CS_DEASRT_CS 0x00000800 // De-assert CS at end
|
||||
#define SPI0_CS_RX_IRQ 0x00000400 // Receive irq enable
|
||||
#define SPI0_CS_DONE_IRQ 0x00000200 // irq when done
|
||||
#define SPI0_CS_DMA_ENABLE 0x00000100 // Run in DMA mode
|
||||
#define SPI0_CS_ACTIVATE 0x00000080 // Activate: be high before starting
|
||||
#define SPI0_CS_CS_POLARIT 0x00000040 // Chip selects active high
|
||||
#define SPI0_CS_CLRTXFIFO 0x00000020 // Clear TX FIFO (auto clear bit)
|
||||
#define SPI0_CS_CLRRXFIFO 0x00000010 // Clear RX FIFO (auto clear bit)
|
||||
#define SPI0_CS_CLRFIFOS 0x00000030 // Clear BOTH FIFOs (auto clear bit)
|
||||
#define SPI0_CS_CLK_IDLHI 0x00000008 // Clock pin is high when idle
|
||||
#define SPI0_CS_CLKTRANS 0x00000004 // 0=first clock in middle of data bit
|
||||
// 1=first clock at begin of data bit
|
||||
#define SPI0_CS_CHIPSEL0 0x00000000 // Use chip select 0
|
||||
#define SPI0_CS_CHIPSEL1 0x00000001 // Use chip select 1
|
||||
#define SPI0_CS_CHIPSEL2 0x00000002 // Use chip select 2
|
||||
#define SPI0_CS_CHIPSELN 0x00000003 // No chip select (e.g. use GPIO pin)
|
||||
|
||||
#define SPI0_CS_CLRALL (SPI0_CS_CLRFIFOS|SPI0_CS_DONE)
|
||||
|
||||
#define ISASC(x) ((x)>=0x20 && (x)<=0x7F)
|
||||
|
||||
void setup_io();
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{ int g;
|
||||
|
||||
setup_io(); // Set up direct access to I/O for GPIO and SPI
|
||||
|
||||
// Switch GPIO 7..11 to SPI mode (ALT function 0)
|
||||
|
||||
/************************************************************************\
|
||||
* You are about to change the GPIO settings of your computer. *
|
||||
* Mess this up and it will stop working! *
|
||||
* It might be a good idea to 'sync' before running this program *
|
||||
* so at least you still have your code changes written to the SD-card! *
|
||||
\************************************************************************/
|
||||
|
||||
for (g=7; g<=11; g++)
|
||||
{
|
||||
INP_GPIO(g); // clear bits (= input)
|
||||
SET_GPIO_ALT(g,0); // set function 0
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
} // main
|
||||
|
||||
|
||||
//
|
||||
// Set up a memory regions to access GPIO and SPI0
|
||||
//
|
||||
void setup_io()
|
||||
{
|
||||
|
||||
/* open /dev/mem */
|
||||
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
|
||||
printf("can't open /dev/mem \n");
|
||||
exit (-1);
|
||||
}
|
||||
|
||||
/* mmap GPIO */
|
||||
if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
|
||||
printf("allocation error \n");
|
||||
exit (-1);
|
||||
}
|
||||
if ((unsigned long)gpio_mem % PAGE_SIZE)
|
||||
gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);
|
||||
|
||||
gpio_map = (unsigned char *)mmap(
|
||||
(caddr_t)gpio_mem,
|
||||
BLOCK_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED|MAP_FIXED,
|
||||
mem_fd,
|
||||
GPIO_BASE
|
||||
);
|
||||
|
||||
if ((long)gpio_map < 0) {
|
||||
printf("mmap error %d\n", (int)gpio_map);
|
||||
exit (-1);
|
||||
}
|
||||
gpio = (volatile unsigned *)gpio_map;
|
||||
|
||||
/* mmap SPI0 */
|
||||
if ((spi0_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
|
||||
printf("allocation error \n");
|
||||
exit (-1);
|
||||
}
|
||||
if ((unsigned long)spi0_mem % PAGE_SIZE)
|
||||
spi0_mem += PAGE_SIZE - ((unsigned long)spi0_mem % PAGE_SIZE);
|
||||
|
||||
spi0_map = (unsigned char *)mmap(
|
||||
(caddr_t)spi0_mem,
|
||||
BLOCK_SIZE,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_SHARED|MAP_FIXED,
|
||||
mem_fd,
|
||||
SPI0_BASE
|
||||
);
|
||||
|
||||
|
||||
printf("SPI mapped from 0x%p to 0x%p\n",SPI0_BASE,spi0_map);
|
||||
|
||||
if ((long)spi0_map < 0) {
|
||||
printf("mmap error %d\n", (int)spi0_map);
|
||||
exit (-1);
|
||||
}
|
||||
spi0 = (volatile unsigned *)spi0_map;
|
||||
|
||||
} // setup_io
|
Loading…
Reference in New Issue
Block a user