diff --git a/.gitignore b/.gitignore index 272d4c32..3cffde1c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ CMakeCache.txt /HyperionConfig.h /lib .directory +*.pyc diff --git a/CMakeLists.txt b/CMakeLists.txt index b969f31f..067ed786 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,24 +16,36 @@ SET ( HYPERION_VERSION_STABLE OFF ) SET ( HYPERION_VERSION_MAJOR 2 ) SET ( HYPERION_VERSION_MINOR 0 ) SET ( HYPERION_VERSION_PATCH 0 ) +SET ( CURRENT_CONFIG_VERSION 2 ) SET ( DEFAULT_AMLOGIC OFF ) SET ( DEFAULT_DISPMANX OFF ) -SET ( DEFAULT_FB ON ) SET ( DEFAULT_OSX OFF ) SET ( DEFAULT_X11 OFF ) -SET ( DEFAULT_SPIDEV ON ) SET ( DEFAULT_WS281XPWM OFF ) -SET ( DEFAULT_V4L2 ON ) SET ( DEFAULT_USE_SHARED_AVAHI_LIBS OFF ) SET ( DEFAULT_USE_AVAHI_LIBS ON ) SET ( DEFAULT_USE_SYSTEM_PROTO_LIBS OFF ) SET ( DEFAULT_TESTS OFF ) +IF ( ${CMAKE_SYSTEM} MATCHES "Linux" ) + SET ( DEFAULT_V4L2 ON ) + SET ( DEFAULT_SPIDEV ON ) + SET ( DEFAULT_FB ON ) +ELSE() + SET ( DEFAULT_V4L2 OFF ) + SET ( DEFAULT_SPIDEV OFF ) + SET ( DEFAULT_FB OFF ) +ENDIF() + if (APPLE) SET( PLATFORM "osx") endif() +if (WIN32) + SET( PLATFORM "windows") +endif() + if ( NOT DEFINED PLATFORM ) if ( "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "x86" ) SET( PLATFORM "x86") @@ -56,16 +68,12 @@ endif() message( STATUS "PLATFORM: ${PLATFORM}") + if ( "${PLATFORM}" MATCHES "osx" ) SET(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "/usr/local/opt/qt5" CACHE STRING "path to your QT5 files" ) include_directories("/opt/X11/include/") SET ( DEFAULT_OSX ON ) - SET ( DEFAULT_V4L2 OFF ) - SET ( DEFAULT_SPIDEV OFF ) - SET ( DEFAULT_FB OFF ) - SET ( DEFAULT_WS281XPWM OFF ) - SET ( DEFAULT_USE_AVAHI_LIBS OFF ) - SET ( DEFAULT_USE_SHARED_AVAHI_LIBS OFF ) + SET ( DEFAULT_USE_AVAHI_LIBS OFF ) elseif ( "${PLATFORM}" STREQUAL "rpi" ) SET ( DEFAULT_DISPMANX ON ) SET ( DEFAULT_WS281XPWM ON ) @@ -83,6 +91,8 @@ elseif ( "${PLATFORM}" MATCHES "x86" ) endif() elseif ( "${PLATFORM}" STREQUAL "imx6" ) SET ( DEFAULT_FB ON ) +elseif ( "${PLATFORM}" STREQUAL "windows" ) + MESSAGE( WARNING "Hyperion is not developed nor tested on MS Windows.") endif() # enable tests for -dev builds @@ -131,6 +141,40 @@ message(STATUS "ENABLE_PROFILER = ${ENABLE_PROFILER}") SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto ) SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto ) +# check all json files +FILE ( GLOB_RECURSE HYPERION_SCHEMAS RELATIVE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/libsrc/*schema*.json ) +SET( JSON_FILES + config/hyperion.config.json.default + ${HYPERION_SCHEMAS} +) +EXECUTE_PROCESS ( + COMMAND python test/jsonchecks/checkjson.py ${JSON_FILES} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE CHECK_JSON_FAILED +) +IF ( ${CHECK_JSON_FAILED} ) + MESSAGE (FATAL_ERROR "check of json files failed" ) +ENDIF () + +EXECUTE_PROCESS ( + COMMAND python test/jsonchecks/checkeffects.py effects effects/schema + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE CHECK_EFFECTS_FAILED +) +IF ( ${CHECK_EFFECTS_FAILED} ) + MESSAGE (FATAL_ERROR "check of json effect files failed" ) +ENDIF () + +EXECUTE_PROCESS ( + COMMAND python test/jsonchecks/checkschema.py config/hyperion.config.json.default libsrc/hyperion/schemas/hyperion.schema-${CURRENT_CONFIG_VERSION}.json + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + RESULT_VARIABLE CHECK_CONFIG_FAILED +) +IF ( ${CHECK_CONFIG_FAILED} ) + MESSAGE (FATAL_ERROR "check of json default config failed" ) +ENDIF () + + # Createt the configuration file # Add project specific cmake modules (find, etc) @@ -207,6 +251,14 @@ endif () # Add the doxygen generation directory add_subdirectory(doc) +# remove generated files on make cleaan too +LIST( APPEND GENERATED_QRC + ${CMAKE_BINARY_DIR}/EffectEngine.qrc + ${CMAKE_BINARY_DIR}/WebConfig.qrc + ${CMAKE_BINARY_DIR}/HyperionConfig.h +) +set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${GENERATED_QRC}" ) + # uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) diff --git a/CompileHowto.md b/CompileHowto.md index f8366088..80bed57e 100644 --- a/CompileHowto.md +++ b/CompileHowto.md @@ -1,12 +1,17 @@ # Install the required tools and dependencies +## Debian/Ubuntu/Win10LinuxSubsystem + ``` sudo apt-get update sudo apt-get install git cmake build-essential qtbase5-dev libqt5serialport5-dev libusb-1.0-0-dev python-dev libxrender-dev libavahi-core-dev libavahi-compat-libdnssd-dev ``` -# RPI Only -when you build on the rapberry pi and include the dispmanx grabber (which is the default) +**ATTENTION Win10LinuxSubsystem** we do not (/we can't) support using hyperion in linux subsystem of MS Windows 10, albeit some users tested it with success. Keep in mind to disable +all linux specific led and grabber hardware via cmake. Because we use QT as framework in hyperion, serialport leds and network driven devices could work. + +## RPI Only +when you build on the rapberry pi and include the dispmanx grabber (which is the default) you also need the firmware including headers installed. This downloads the firmware from the raspberrypi github and copies the required files to the correct place. The firmware directory can be deleted afterwards if desired. @@ -16,7 +21,47 @@ git clone --depth 1 https://github.com/raspberrypi/firmware.git "$FIRMWARE_DIR" sudo cp -R "$FIRMWARE_DIR/hardfp/opt/" /opt ``` -# Create hyperion directory and checkout the code from github +## Arch +See [AUR](https://aur.archlinux.org/packages/?O=0&SeB=nd&K=hyperion&outdated=&SB=n&SO=a&PP=50&do_Search=Go) for PKGBUILDs on arch. If the PKGBUILD does not work ask questions there please. + + +## OSX +To install on OS X you either need Homebrew or Macport but Homebrew is the recommended way to install the packages. To use Homebrew XCode is required as well, use `brew doctor` to check your install. + +First you need to install the dependencies: +``` +brew install qt5 +brew install cmake +brew install libusb +brew install doxygen +``` + + +# Compiling and installing Hyperion + +### The general quick way (without big comments) +be sure you fullfill the prerequisites above. + +assume your home is /home/pi +```bash +git clone --recursive https://github.com/hyperion-project/hyperion.ng.git hyperion +cd hyperion +mkdir build +cd build +cmake -DCMAKE_BUILD_TYPE=Release .. +make -j $(nproc) +# optional: install into your system +make install/strip +# to uninstall (not very well tested, please keep that in mind) +make uninstall +# ... or run it from compile directory +bin/hyperiond myconfig.json +# webui is located on localhost:8099 +``` + + +### Download + Create hyperion directory and checkout the code from github You might want to add `--depth 1` to the `git` command if you only want to compile the current source and have no need for the entire git repository @@ -31,32 +76,26 @@ git submodule init git submodule update ``` -# Create and enter the build directory +### Preparations +Change into hyperion folder and create a build folder ``` -mkdir "$HYPERION_DIR/build" -cd "$HYPERION_DIR/build" +cd "$HYPERION_DIR" +mkdir build +cd build ``` -# Generate the make files: +### Generate the make files: -To generate make files on the raspberry pi WITHOUT PWM SUPPORT: +To generate make files with automatic platform detection and default settings: + +This should fit to *RPI, x86, amlogic/wetek* ``` -cmake -DPLATFORM=rpi -DCMAKE_BUILD_TYPE=Release .. +cmake -DCMAKE_BUILD_TYPE=Release .. ``` -To generate make files on the raspberry pi WITH PWM SUPPORT: +*Developers on x86* linux should use: ``` -cmake -DPLATFORM=rpi-pwm -DCMAKE_BUILD_TYPE=Release .. -``` - -To generate make files on a regular x86 or amd64 system: -``` -cmake -DPLATFORM=x86 -DCMAKE_BUILD_TYPE=Release .. -``` - -To generate make files on a amlogic system: -``` -cmake -DPLATFORM=aml -DCMAKE_BUILD_TYPE=Release .. +cmake -DPLATFORM=x86-dev -DCMAKE_BUILD_TYPE=Release .. ``` To use framebuffer instead of dispmanx (for example on the *cubox-i*): @@ -66,24 +105,14 @@ cmake -DENABLE_FB=ON -DCMAKE_BUILD_TYPE=Release .. To generate make files on OS X: -To install on OS X you either need Homebrew or Macport but Homebrew is the recommended way to install the packages. To use Homebrew XCode is required as well, use `brew doctor` to check your install. - -First you need to install the dependencies: -``` -brew install qt5 -brew install cmake -brew install libusb -brew install doxygen -``` - After which you can run cmake with the correct qt5 path: ``` -cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.7.0 .. +cmake -DCMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.7.0 -DCMAKE_BUILD_TYPE=Release .. ``` -# Run make to build Hyperion +### Run make to build Hyperion The `-j $(nproc)` specifies the amount of CPU cores to use. -``` +```bash make -j $(nproc) ``` @@ -91,39 +120,25 @@ On a mac you can use ``sysctl -n hw.ncpu`` to get the number of available CPU co ```bash make -j $(sysctl -n hw.ncpu) -``` - - -#After compile, to remove any stuff not needed for a release version. -``` -strip bin/* -``` -# The binaries are build in "$HYPERION_DIR/build/bin". You could copy those to /usr/bin -``` -sudo cp ./bin/hyperion-remote /usr/bin/ -sudo cp ./bin/hyperiond /usr/bin/ ``` -On a Mac with Sierra you won't be able to copy these files to the ``/usr/bin/`` folder due to Sierra's file protection. You can copy those files to ``/usr/local/bin`` instead. - -```bash -cp ./bin/hyperion-remote /usr/local/bin -cp ./bin/hyperiond /usr/local/bin -``` - -The better way to do this is to use the make install script, which copies all necessary files to ``/usr/local/share/hyperion``: - -```bash -sudo make install -``` - -You can combine the install command with the strip command to install and cleanup in one task: +### Install hyperion into your system +Copy all necessary files to ``/usr/local/share/hyperion`` ```bash sudo make install/strip ``` -# Copy the effect folder (if you did not use the normal installation methode before) -``` -sudo mkdir -p /usr/local/share/hyperion/effects && sudo cp -R ../effects/ /usr/local/share/hyperion/effects/ +If you want to install into another location call this before installing + +```bash +cmake -DCMAKE_INSTALL_PREFIX=/home/pi/apps .. ``` +This will install to ``/home/pi/apps/share/hyperion`` + + +### Integrating hyperion into your system + +... ToDo + + diff --git a/HyperionConfig.h.in b/HyperionConfig.h.in index 2d090991..483d4ab7 100644 --- a/HyperionConfig.h.in +++ b/HyperionConfig.h.in @@ -30,6 +30,9 @@ // Define to enable profiler for development purpose #cmakedefine ENABLE_PROFILER +// Define version id of current config +#define CURRENT_CONFIG_VERSION ${CURRENT_CONFIG_VERSION} + // the hyperion build id string #define HYPERION_BUILD_ID "${HYPERION_BUILD_ID}" @@ -39,3 +42,5 @@ #define HYPERION_VERSION "${HYPERION_VERSION_MAJOR}.${HYPERION_VERSION_MINOR}.${HYPERION_VERSION_PATCH}" #define HYPERION_JSON_VERSION "1.0.0" + + diff --git a/README.md b/README.md index b200a359..cc786d56 100644 --- a/README.md +++ b/README.md @@ -3,22 +3,38 @@ HYPERION This is a pre alpha development repository for the next major version of hyperion -Feel free to join us! We are looking always for people who wants to participate. +-------- +## **Important notice!** +Hyperion.NG is under heavy development. This version is currently _only for development_ purpose. +Please do not use it for your 'productiv' setup! -Current new deps (libs) -QT5 -- sudo apt-get install libqt5core5a libqt5network5 libqt5gui5 libqt5serialport5 libusb-1.0-0 +If you want to use hyperion as 'normal user', please use [current stable version](https://github.com/hyperion-project/hyperion) -zeroconf -- apt-get install libavahi-core-dev libavahi-compat-libdnssd-dev +Besides of that .... Feel free to join us! We are looking always for people who wants to participate. +-------- -94MB free disc space for deps +Hyperion is an opensource 'AmbiLight' implementation with support for many LED devices and video grabbers. -More information can be found on the official Hyperion [Wiki](https://wiki.hyperion-project.org) +The main features of Hyperion are: +* Low CPU load makes it perfect for SoCs like Raspberry Pi +* Json interface which allows easy integration into scripts +* A command line utility to for testing and integration in automated environment +* 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). +* Kodi-checker which checks the playing status of Kodi and decides whether or not to capture the screen. +* Black border detector. +* A scriptable (Python) effect engine +* A web ui to configure and remote control hyperion + +More information can be found on the official Hyperion [Wiki](https://wiki.hyperion-project.org) If you need further support please open a topic at the our new forum! [Hyperion webpage/forum](https://www.hyperion-project.org). +## Building + +See [Compilehowto](CompileHowto.md) and [CrossCompileHowto](CrossCompileHowto.txt). + +## License The source is released under MIT-License (see http://opensource.org/licenses/MIT). diff --git a/assets/firmware/arduino/adalight/adalight.ino b/assets/firmware/arduino/adalight/adalight.ino index 6f8b0869..d7ce571c 100644 --- a/assets/firmware/arduino/adalight/adalight.ino +++ b/assets/firmware/arduino/adalight/adalight.ino @@ -9,12 +9,13 @@ set following values to your needs **************************************/ -// Number of leds in your strip. set to 1 and ANALOG_OUTPUT_ENABLED to true to activate analog only +#define INITAL_LED_TEST_ENABLED true + +// Number of leds in your strip. set to "1" and ANALOG_OUTPUT_ENABLED to "true" to activate analog only #define NUM_LEDS 100 - -#define SPI_LEDS false // connection type. Set "true" for 4 wire and "false" for 3 Wire stripes. -#define LED_TYPE WS2812B // type of your led controller, possible values, see below +// type of your led controller, possible values, see below +#define LED_TYPE WS2812B // 3 wire (pwm): NEOPIXEL BTM1829 TM1812 TM1809 TM1804 TM1803 UCS1903 UCS1903B UCS1904 UCS2903 WS2812 WS2852 // S2812B SK6812 SK6822 APA106 PL9823 WS2811 WS2813 APA104 WS2811_40 GW6205 GW6205_40 LPD1886 LPD1886_8BIT @@ -22,8 +23,10 @@ // For 3 wire led stripes line Neopixel/Ws2812, which have a data line, ground, and power, you just need to define DATA_PIN. // For led chipsets that are SPI based (four wires - data, clock, ground, and power), both defines DATA_PIN and CLOCK_PIN are needed -#define DATA_PIN 6 -#define CLOCK_PIN 13 + +// DATA_PIN, or DATA_PIN, CLOCK_PIN +#define LED_PINS 6 // 3 wire leds +//#define LED_PINS 6, 13 // 4 wire leds #define COLOR_ORDER GRB // colororder of the stripe, set RGB in hyperion @@ -33,7 +36,7 @@ // ATTENTION this pin config is default for atmega328 based arduinos, others might work to // if you have flickering analog leds this might be caused by unsynced pwm signals // try other pins is more or less the only thing that helps -#define ANALOG_OUTPUT_ENABLED true +#define ANALOG_OUTPUT_ENABLED false #define ANALOG_MODE ANALOG_MODE_LAST_LED // use ANALOG_MODE_AVERAGE or ANALOG_MODE_LAST_LED #define ANALOG_GROUND_PIN 8 // additional ground pin to make wiring a bit easier #define ANALOG_RED_PIN 9 @@ -48,7 +51,8 @@ #define BRIGHTNESS 255 // maximum brightness 0-255 #define DITHER_MODE BINARY_DITHER // BINARY_DITHER or DISABLE_DITHER #define COLOR_TEMPERATURE CRGB(255,255,255) // RGB value describing the color temperature -#define COLOR_CORRECTION CRGB(255,255,255) // RGB value describing the color correction +#define COLOR_CORRECTION TypicalLEDStrip // predefined fastled color correction +//#define COLOR_CORRECTION CRGB(255,255,255) // or RGB value describing the color correction // Baudrate, higher rate allows faster refresh rate and more LEDs (defined in /etc/boblight.conf) #define serialRate 460800 // use 115200 for ftdi based boards @@ -90,7 +94,7 @@ void showColor(const CRGB& led) { // switch of digital and analog leds void switchOff() { - #if ANALOG_ONLY == false + #if NUM_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false memset(leds, 0, NUM_LEDS * sizeof(struct CRGB)); FastLED.show(); #endif @@ -133,13 +137,9 @@ void setup() { } #if NUM_LEDS > 1 || ANALOG_OUTPUT_ENABLED == false - #if SPI_LEDS == true - FastLED.addLeds(leds, ledCount); - #else - FastLED.addLeds(leds, ledCount); - #endif + FastLED.addLeds(leds, ledCount); #endif - + // color adjustments FastLED.setBrightness ( BRIGHTNESS ); FastLED.setTemperature( COLOR_TEMPERATURE ); @@ -147,11 +147,13 @@ void setup() { FastLED.setDither ( DITHER_MODE ); // initial RGB flash + #if INITAL_LED_TEST_ENABLED == true showColor(CRGB(255, 0, 0)); delay(400); showColor(CRGB(0, 255, 0)); delay(400); showColor(CRGB(0, 0, 255)); delay(400); + #endif showColor(CRGB(0, 0, 0)); - + Serial.begin(serialRate); Serial.print("Ada\n"); // Send "Magic Word" string to host @@ -161,7 +163,7 @@ void setup() { // loop() is avoided as even that small bit of function overhead // has a measurable impact on this code's overall throughput. - while (true) { + for(;;) { // wait for first byte of Magic Word for (i = 0; i < sizeof prefix; ++i) { // If next byte is not in Magic Word, the start over diff --git a/assets/firmware/arduino/adalight_lightberry_apa102/LightberryHDUSBAPA1021.1.ino b/assets/firmware/arduino/adalight_lightberry_apa102/LightberryHDUSBAPA1021.1.ino new file mode 100644 index 00000000..000a8815 --- /dev/null +++ b/assets/firmware/arduino/adalight_lightberry_apa102/LightberryHDUSBAPA1021.1.ino @@ -0,0 +1,273 @@ +// Arduino "bridge" code between host computer and WS2801-based digital +// RGB LED pixels (e.g. Adafruit product ID #322). Intended for use +// with USB-native boards such as Teensy or Adafruit 32u4 Breakout; +// works on normal serial Arduinos, but throughput is severely limited. +// LED data is streamed, not buffered, making this suitable for larger +// installations (e.g. video wall, etc.) than could otherwise be held +// in the Arduino's limited RAM. + +// Some effort is put into avoiding buffer underruns (where the output +// side becomes starved of data). The WS2801 latch protocol, being +// delay-based, could be inadvertently triggered if the USB bus or CPU +// is swamped with other tasks. This code buffers incoming serial data +// and introduces intentional pauses if there's a threat of the buffer +// draining prematurely. The cost of this complexity is somewhat +// reduced throughput, the gain is that most visual glitches are +// avoided (though ultimately a function of the load on the USB bus and +// host CPU, and out of our control). + +// LED data and clock lines are connected to the Arduino's SPI output. +// On traditional Arduino boards, SPI data out is digital pin 11 and +// clock is digital pin 13. On both Teensy and the 32u4 Breakout, +// data out is pin B2, clock is B1. LEDs should be externally +// powered -- trying to run any more than just a few off the Arduino's +// 5V line is generally a Bad Idea. LED ground should also be +// connected to Arduino ground. + +// -------------------------------------------------------------------- +// This file is part of Adalight. + +// Adalight is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. + +// Adalight is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. + +// You should have received a copy of the GNU Lesser General Public +// License along with Adalight. If not, see +// . +// -------------------------------------------------------------------- + +#include + +// LED pin for Adafruit 32u4 Breakout Board: +//#define LED_DDR DDRE +//#define LED_PORT PORTE +//#define LED_PIN _BV(PORTE6) +// LED pin for Teensy: +//#define LED_DDR DDRD +//#define LED_PORT PORTD +//#define LED_PIN _BV(PORTD6) +// LED pin for Arduino: +#define LED_DDR DDRB +#define LED_PORT PORTB +#define LED_PIN _BV(PORTB5) + +// A 'magic word' (along with LED count & checksum) precedes each block +// of LED data; this assists the microcontroller in syncing up with the +// host-side software and properly issuing the latch (host I/O is +// likely buffered, making usleep() unreliable for latch). You may see +// an initial glitchy frame or two until the two come into alignment. +// The magic word can be whatever sequence you like, but each character +// should be unique, and frequent pixel values like 0 and 255 are +// avoided -- fewer false positives. The host software will need to +// generate a compatible header: immediately following the magic word +// are three bytes: a 16-bit count of the number of LEDs (high byte +// first) followed by a simple checksum value (high byte XOR low byte +// XOR 0x55). LED data follows, 3 bytes per LED, in order R, G, B, +// where 0 = off and 255 = max brightness. + +static const uint8_t magic[] = {'A','d','a'}; +#define MAGICSIZE sizeof(magic) +#define HEADERSIZE (MAGICSIZE + 3) + +#define MODE_HEADER 0 +#define MODE_HOLD 1 +#define MODE_DATA 2 + +#define DATA_LED A5 +#define SPI_LED A3 + +// If no serial data is received for a while, the LEDs are shut off +// automatically. This avoids the annoying "stuck pixel" look when +// quitting LED display programs on the host computer. +static const unsigned long serialTimeout = 15000; // 15 seconds + +void setup() +{ + // Dirty trick: the circular buffer for serial data is 256 bytes, + // and the "in" and "out" indices are unsigned 8-bit types -- this + // much simplifies the cases where in/out need to "wrap around" the + // beginning/end of the buffer. Otherwise there'd be a ton of bit- + // masking and/or conditional code every time one of these indices + // needs to change, slowing things down tremendously. + uint8_t + buffer[256], + indexIn = 0, + indexOut = 0, + mode = MODE_HEADER, + hi, lo, chk, i, spiFlag; + int16_t + bytesBuffered = 0, + hold = 0, + c; + int32_t + bytesRemaining; + unsigned long + startTime, + lastByteTime, + lastAckTime, + t; + bool + data_in_led = false, + spi_out_led = false; + + LED_DDR |= LED_PIN; // Enable output for LED + LED_PORT &= ~LED_PIN; // LED off + pinMode(DATA_LED, OUTPUT); //data in led + pinMode(SPI_LED, OUTPUT); //data out led + + delay(5000); + + Serial.begin(115200); // Teensy/32u4 disregards baud rate; is OK! + + SPI.begin(); + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + SPI.setClockDivider(SPI_CLOCK_DIV16); // 1 MHz max, else flicker + + // Issue test pattern to LEDs on startup. This helps verify that + // wiring between the Arduino and LEDs is correct. Not knowing the + // actual number of LEDs connected, this sets all of them (well, up + // to the first 25,000, so as not to be TOO time consuming) to red, + // green, blue, then off. Once you're confident everything is working + // end-to-end, it's OK to comment this out and reprogram the Arduino. + uint8_t testcolor[] = { 0, 0, 0, 255, 0, 0 }; + for(int i=0; i<5; i++){ + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + } + for(char n=3; n>=0; n--) { + for(c=0; c<25000; c++) { + for(i=0; i<3; i++) { + for(SPDR = testcolor[n + i]; !(SPSR & _BV(SPIF)); ); + } + for(i=0; i<1; i++) { + for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); + } + } + for(int i=0; i<16; i++){ + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + } + delay(1); // One millisecond pause = latch + digitalWrite(SPI_LED, spi_out_led = !spi_out_led); + } + + Serial.print("Ada\n"); // Send ACK string to host + + startTime = micros(); + lastByteTime = lastAckTime = millis(); + + // loop() is avoided as even that small bit of function overhead + // has a measurable impact on this code's overall throughput. + + for(;;) { + digitalWrite(DATA_LED, LOW); + digitalWrite(SPI_LED, LOW); + // Implementation is a simple finite-state machine. + // Regardless of mode, check for serial input each time: + t = millis(); + if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) { + buffer[indexIn++] = c; + bytesBuffered++; + lastByteTime = lastAckTime = t; // Reset timeout counters + } else { + // No data received. If this persists, send an ACK packet + // to host once every second to alert it to our presence. + if((t - lastAckTime) > 1000) { + Serial.print("Ada\n"); // Send ACK string to host + lastAckTime = t; // Reset counter + } + // If no data received for an extended time, turn off all LEDs. + if((t - lastByteTime) > serialTimeout) { + for(c=0; c<25000; c++) { + for(i=0; i<3; i++) { + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + } + for(i=0; i<1; i++) { + for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); + } + } + delay(1); // One millisecond pause = latch + lastByteTime = t; // Reset counter + } + } + + switch(mode) { + + case MODE_HEADER: + + // In header-seeking mode. Is there enough data to check? + if(bytesBuffered >= HEADERSIZE) { + // Indeed. Check for a 'magic word' match. + for(i=0; (i 0) and multiply by 3 for R,G,B. + bytesRemaining = 4L * (256L * (long)hi + (long)lo) +4L + (256L *(long)hi + (long)lo +15)/16; + bytesBuffered -= 3; + spiFlag = 0; // No data out yet + mode = MODE_HOLD; // Proceed to latch wait mode + digitalWrite(DATA_LED, data_in_led = !data_in_led); + } else { + // Checksum didn't match; search resumes after magic word. + indexOut -= 3; // Rewind + } + } // else no header match. Resume at first mismatched byte. + bytesBuffered -= i; + } + break; + + case MODE_HOLD: + + // Ostensibly "waiting for the latch from the prior frame + // to complete" mode, but may also revert to this mode when + // underrun prevention necessitates a delay. + + if((micros() - startTime) < hold) break; // Still holding; keep buffering + + // Latch/delay complete. Advance to data-issuing mode... + LED_PORT &= ~LED_PIN; // LED off + mode = MODE_DATA; // ...and fall through (no break): + + case MODE_DATA: + digitalWrite(SPI_LED, spi_out_led = !spi_out_led); + while(spiFlag && !(SPSR & _BV(SPIF))); // Wait for prior byte + if(bytesRemaining > 0) { + if(bytesBuffered > 0) { + SPDR = buffer[indexOut++]; // Issue next byte + bytesBuffered--; + bytesRemaining--; + spiFlag = 1; + } + // If serial buffer is threatening to underrun, start + // introducing progressively longer pauses to allow more + // data to arrive (up to a point). + // if((bytesBuffered < 32) && (bytesRemaining > bytesBuffered)) { + // startTime = micros(); + // hold = 100 + (32 - bytesBuffered) * 10; + // mode = MODE_HOLD; +//} + } else { + // End of data -- issue latch: + startTime = micros(); + hold = 1000; // Latch duration = 1000 uS + LED_PORT |= LED_PIN; // LED on + mode = MODE_HEADER; // Begin next header search + } + } // end switch + } // end for(;;) +} + +void loop() +{ + // Not used. See note in setup() function. +} diff --git a/assets/firmware/arduino/adalightapa102/LightberryHDUSBAPA1021.1.ino b/assets/firmware/arduino/adalight_lightberry_ws2801/LightberryHDUSB1.1.ino similarity index 60% rename from assets/firmware/arduino/adalightapa102/LightberryHDUSBAPA1021.1.ino rename to assets/firmware/arduino/adalight_lightberry_ws2801/LightberryHDUSB1.1.ino index 603599c9..0f14b0e2 100644 --- a/assets/firmware/arduino/adalightapa102/LightberryHDUSBAPA1021.1.ino +++ b/assets/firmware/arduino/adalight_lightberry_ws2801/LightberryHDUSB1.1.ino @@ -71,7 +71,7 @@ // XOR 0x55). LED data follows, 3 bytes per LED, in order R, G, B, // where 0 = off and 255 = max brightness. -static const uint8_t magic[] = {'A', 'd', 'a'}; +static const uint8_t magic[] = {'A','d','a'}; #define MAGICSIZE sizeof(magic) #define HEADERSIZE (MAGICSIZE + 3) @@ -96,37 +96,39 @@ void setup() // masking and/or conditional code every time one of these indices // needs to change, slowing things down tremendously. uint8_t - buffer[256], - indexIn = 0, - indexOut = 0, - mode = MODE_HEADER, - hi, lo, chk, i, spiFlag; + buffer[256], + indexIn = 0, + indexOut = 0, + mode = MODE_HEADER, + hi, lo, chk, i, spiFlag; int16_t - bytesBuffered = 0, - hold = 0, - c; + bytesBuffered = 0, + hold = 0, + c; int32_t - bytesRemaining; + bytesRemaining; unsigned long - startTime, - lastByteTime, - lastAckTime, - t; - bool - data_in_led = false, - spi_out_led = false; - + startTime, + lastByteTime, + lastAckTime, + t; + bool + data_in_led = false, + spi_out_led = false; + LED_DDR |= LED_PIN; // Enable output for LED LED_PORT &= ~LED_PIN; // LED off pinMode(DATA_LED, OUTPUT); //data in led pinMode(SPI_LED, OUTPUT); //data out led + delay(5000); + Serial.begin(115200); // Teensy/32u4 disregards baud rate; is OK! SPI.begin(); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE0); - SPI.setClockDivider(SPI_CLOCK_DIV8); // 2Mhz + SPI.setClockDivider(SPI_CLOCK_DIV16); // 1 MHz max, else flicker // Issue test pattern to LEDs on startup. This helps verify that // wiring between the Arduino and LEDs is correct. Not knowing the @@ -135,23 +137,24 @@ void setup() // green, blue, then off. Once you're confident everything is working // end-to-end, it's OK to comment this out and reprogram the Arduino. uint8_t testcolor[] = { 0, 0, 0, 255, 0, 0 }; - for (char n = 3; n >= 0; n--) { - for (int i = 0; i < 4; i++) { //Start Frame - for (SPDR = 0x00; !(SPSR & _BV(SPIF)); ); - } - for (c = 0; c < 25000; c++) { - for (SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); //Brightness byte - for (i = 0; i < 3; i++) { - for (SPDR = testcolor[n + i]; !(SPSR & _BV(SPIF)); ); //BGR + for(int i=0; i<5; i++){ + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + } + for(char n=3; n>=0; n--) { + for(c=0; c<25000; c++) { + for(i=0; i<3; i++) { + for(SPDR = testcolor[n + i]; !(SPSR & _BV(SPIF)); ); + } + for(i=0; i<1; i++) { + for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); } } - for (int i = 0; i < 4; i++) { //Stop Frame - for (SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); + for(int i=0; i<16; i++){ + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); } - delay(1); // One millisecond pause = latch + digitalWrite(SPI_LED, spi_out_led = !spi_out_led); } - digitalWrite(SPI_LED, spi_out_led = !spi_out_led); Serial.print("Ada\n"); // Send ACK string to host @@ -161,109 +164,105 @@ void setup() // loop() is avoided as even that small bit of function overhead // has a measurable impact on this code's overall throughput. - for (;;) { + for(;;) { digitalWrite(DATA_LED, LOW); digitalWrite(SPI_LED, LOW); // Implementation is a simple finite-state machine. // Regardless of mode, check for serial input each time: t = millis(); - if ((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) { + if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) { buffer[indexIn++] = c; bytesBuffered++; lastByteTime = lastAckTime = t; // Reset timeout counters } else { // No data received. If this persists, send an ACK packet // to host once every second to alert it to our presence. - if ((t - lastAckTime) > 1000) { + if((t - lastAckTime) > 1000) { Serial.print("Ada\n"); // Send ACK string to host lastAckTime = t; // Reset counter } // If no data received for an extended time, turn off all LEDs. - if ((t - lastByteTime) > serialTimeout) { - for (i = 0; i < 4; i++) { //Start Frame - for (SPDR = 0x00; !(SPSR & _BV(SPIF)); ); - } - for (c = 0; c < 25000; c++) { - for (SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); //Brightness Byte - for (i = 0; i < 3; i++) { - for (SPDR = 0x00; !(SPSR & _BV(SPIF)); ); //BGR + if((t - lastByteTime) > serialTimeout) { + for(c=0; c<25000; c++) { + for(i=0; i<3; i++) { + for(SPDR = 0x00; !(SPSR & _BV(SPIF)); ); + } + for(i=0; i<1; i++) { + for(SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); + } } - } - for (i = 0; i < 4; i++) { //Stop Frame - for (SPDR = 0xFF; !(SPSR & _BV(SPIF)); ); - } delay(1); // One millisecond pause = latch lastByteTime = t; // Reset counter } } - switch (mode) { + switch(mode) { - case MODE_HEADER: + case MODE_HEADER: - // In header-seeking mode. Is there enough data to check? - if (bytesBuffered >= HEADERSIZE) { - // Indeed. Check for a 'magic word' match. - for (i = 0; (i < MAGICSIZE) && (buffer[indexOut++] == magic[i++]);); - if (i == MAGICSIZE) { - // Magic word matches. Now how about the checksum? - hi = buffer[indexOut++]; - lo = buffer[indexOut++]; - chk = buffer[indexOut++]; - if (chk == (hi ^ lo ^ 0x55)) { - // Checksum looks valid. Get 16-bit LED count, add 1 - // (# LEDs is always > 0) and multiply by 3 for R,G,B. - bytesRemaining = 4L * (256L * (long)hi + (long)lo) + 4L + (256L * (long)hi + (long)lo + 15) / 16; - bytesBuffered -= 3; - spiFlag = 0; // No data out yet - mode = MODE_HOLD; // Proceed to latch wait mode - digitalWrite(DATA_LED, data_in_led = !data_in_led); - } else { - // Checksum didn't match; search resumes after magic word. - indexOut -= 3; // Rewind - } - } // else no header match. Resume at first mismatched byte. - bytesBuffered -= i; - } - break; - - case MODE_HOLD: - - // Ostensibly "waiting for the latch from the prior frame - // to complete" mode, but may also revert to this mode when - // underrun prevention necessitates a delay. - - if ((micros() - startTime) < hold) break; // Still holding; keep buffering - - // Latch/delay complete. Advance to data-issuing mode... - LED_PORT &= ~LED_PIN; // LED off - mode = MODE_DATA; // ...and fall through (no break): - - case MODE_DATA: - digitalWrite(SPI_LED, spi_out_led = !spi_out_led); - while (spiFlag && !(SPSR & _BV(SPIF))); // Wait for prior byte - if (bytesRemaining > 0) { - if (bytesBuffered > 0) { - SPDR = buffer[indexOut++]; // Issue next byte - bytesBuffered--; - bytesRemaining--; - spiFlag = 1; + // In header-seeking mode. Is there enough data to check? + if(bytesBuffered >= HEADERSIZE) { + // Indeed. Check for a 'magic word' match. + for(i=0; (i 0) and multiply by 3 for R,G,B. + bytesRemaining = 4L * (256L * (long)hi + (long)lo) +4L + (256L *(long)hi + (long)lo +15)/16; + bytesBuffered -= 3; + spiFlag = 0; // No data out yet + mode = MODE_HOLD; // Proceed to latch wait mode + digitalWrite(DATA_LED, data_in_led = !data_in_led); + } else { + // Checksum didn't match; search resumes after magic word. + indexOut -= 3; // Rewind } - // If serial buffer is threatening to underrun, start - // introducing progressively longer pauses to allow more - // data to arrive (up to a point). - if ((bytesBuffered < 32) && (bytesRemaining > bytesBuffered)) { - startTime = micros(); - hold = 100 + (32 - bytesBuffered) * 10; - mode = MODE_HOLD; - } - } else { - // End of data -- issue latch: - startTime = micros(); - hold = 1000; // Latch duration = 1000 uS - LED_PORT |= LED_PIN; // LED on - mode = MODE_HEADER; // Begin next header search + } // else no header match. Resume at first mismatched byte. + bytesBuffered -= i; + } + break; + + case MODE_HOLD: + + // Ostensibly "waiting for the latch from the prior frame + // to complete" mode, but may also revert to this mode when + // underrun prevention necessitates a delay. + + if((micros() - startTime) < hold) break; // Still holding; keep buffering + + // Latch/delay complete. Advance to data-issuing mode... + LED_PORT &= ~LED_PIN; // LED off + mode = MODE_DATA; // ...and fall through (no break): + + case MODE_DATA: + digitalWrite(SPI_LED, spi_out_led = !spi_out_led); + while(spiFlag && !(SPSR & _BV(SPIF))); // Wait for prior byte + if(bytesRemaining > 0) { + if(bytesBuffered > 0) { + SPDR = buffer[indexOut++]; // Issue next byte + bytesBuffered--; + bytesRemaining--; + spiFlag = 1; } + // If serial buffer is threatening to underrun, start + // introducing progressively longer pauses to allow more + // data to arrive (up to a point). + if((bytesBuffered < 32) && (bytesRemaining > bytesBuffered)) { + startTime = micros(); + hold = 100 + (32 - bytesBuffered) * 10; + mode = MODE_HOLD; + } + } else { + // End of data -- issue latch: + startTime = micros(); + hold = 1000; // Latch duration = 1000 uS + LED_PORT |= LED_PIN; // LED on + mode = MODE_HEADER; // Begin next header search + } } // end switch } // end for(;;) } diff --git a/assets/firmware/arduino/tpm2/tpm2.ino b/assets/firmware/arduino/tpm2/tpm2.ino new file mode 100644 index 00000000..55c95c46 --- /dev/null +++ b/assets/firmware/arduino/tpm2/tpm2.ino @@ -0,0 +1,133 @@ +/** + * This is a demo implemention how to use tpm2 protovol on arduino + * + * code is taken from: https://github.com/JonasVanGool/TPM2-ARDUINO + */ + + +#include + +#define START_BYTE 0xC9 +#define STOP_BYTE 0x36 +#define DATA_FRAME 0xDA +#define COMMAND 0xC0 +#define REQ_RESP 0xAA + +#define BAUDRATE 115200 + +#define DATA_PIN 12 +#define MAX_NR_LEDS 200 + +CRGB leds[MAX_NR_LEDS]; + +enum States { + ST_START, + ST_PACKET_TYPE, + ST_PAYLOAD_SIZE, + ST_USER_DATA, + ST_END +}; + +States activeState = ST_START; +uint8_t byteRead = 0; +uint8_t payloadHighByte = 0; +uint8_t payloadLowByte = 0; +int payloadSize = 0; +int bytesRead = 0; +int nrOfLeds = 0; + +boolean flag = false; +void setup() { + // Init leds + for (int i = 0; i < MAX_NR_LEDS; i++) + leds[i] = 0; + // Start serial device + Serial.begin(BAUDRATE); + // Set time out for readBytes function + Serial.setTimeout(100); + // init fastLED Library + LEDS.addLeds(leds, MAX_NR_LEDS); + // setting brightness to 50% brightness + LEDS.setBrightness(128); + // debug led + pinMode(13, OUTPUT); + + + for(;;) { + if (Serial.available() > 0) { + // process TPM2 protocol + switch (activeState) { + //------------------------------// + // START // + //------------------------------// + case ST_START: + // read incomming byte + byteRead = Serial.read(); + if (byteRead == START_BYTE) { + activeState = ST_PACKET_TYPE; + } + break; + //------------------------------// + // PACKET_TYPE // + //------------------------------// + case ST_PACKET_TYPE: + // read incomming byte + byteRead = Serial.read(); + if (byteRead == DATA_FRAME) { + activeState = ST_PAYLOAD_SIZE; + } else { + activeState = ST_START; + Serial.flush(); + } + break; + //------------------------------// + // PAYLOAD_SIZE // + //------------------------------// + case ST_PAYLOAD_SIZE: + payloadHighByte = Serial.read(); + while (Serial.available() == 0) {} + payloadLowByte = Serial.read(); + payloadSize = (payloadHighByte << 8) + payloadLowByte; + nrOfLeds = payloadSize / 3; + if (nrOfLeds <= MAX_NR_LEDS) { + activeState = ST_USER_DATA; + } else { + activeState = ST_START; + Serial.flush(); + } + break; + //------------------------------// + // USER_DATA // + //------------------------------// + case ST_USER_DATA: + bytesRead = Serial.readBytes((char *)leds, payloadSize); + LEDS.show(); + if (bytesRead == payloadSize) { + activeState = ST_END; + } else { + activeState = ST_START; + Serial.flush(); + } + break; + //------------------------------// + // END // + //------------------------------// + case ST_END: + // read incomming byte + byteRead = Serial.read(); + if (byteRead == STOP_BYTE) { + activeState = ST_START; + } else { + activeState = ST_START; + Serial.flush(); + } + break; + default: break; + } + } + + } +} + +void loop() { +} diff --git a/assets/webconfig/content/colors.html b/assets/webconfig/content/colors.html index 81af1370..16152f1a 100644 --- a/assets/webconfig/content/colors.html +++ b/assets/webconfig/content/colors.html @@ -2,16 +2,12 @@
- +
-

Color calibration, smoothing (color transistions) and detection of blackbars.

-
+

Color calibration, smoothing (color transistions) and detection of blackbars.


-
-
-
- +
diff --git a/assets/webconfig/content/connection_lost.html b/assets/webconfig/content/connection_lost.html index bf4927af..fe55226e 100644 --- a/assets/webconfig/content/connection_lost.html +++ b/assets/webconfig/content/connection_lost.html @@ -1,28 +1,28 @@ -
+
Redefine ambient light!
-

Lost connection to Hyperion service!

+

Lost connection to Hyperion service!


-

Possible reasons:

-

- Hyperion restarts

-

- You perform an update

-

- Hyperion isn't running

+

Possible reasons:

+

- Hyperion restarts

+

- You perform an update

+

- Hyperion isn't running


-

This page will be automatically refreshed.

-

We reconnect again after Hyperion is available.

- If not, click me or reload the page +

This page will be automatically refreshed.

+

We reconnect again after Hyperion is available.

+ If not, click me or reload the page
-
diff --git a/assets/webconfig/content/dashboard.html b/assets/webconfig/content/dashboard.html index 591cc0df..b8b837f0 100644 --- a/assets/webconfig/content/dashboard.html +++ b/assets/webconfig/content/dashboard.html @@ -1,34 +1,35 @@
- +
-

The dashboard give you a quick overview about the status of Hyperion and show you the latest news of the Hyperion Blog.

+

The dashboard give you a quick overview about the status of Hyperion and show you the latest news of the Hyperion Blog.

+
-
+
- Information + Information
- + - + - + - + @@ -42,14 +43,14 @@
- Components status + Components status
Your Hyperion version:Your Hyperion version: unknown
Latest version:Latest version: unknown
LED type:LED type: unknown
Device:Device:
- - + + @@ -62,14 +63,14 @@
- Latest blog posts + Latest blog posts
- + @@ -77,3 +78,6 @@ + \ No newline at end of file diff --git a/assets/webconfig/content/effects.html b/assets/webconfig/content/effects.html index 019d17f9..d006d263 100644 --- a/assets/webconfig/content/effects.html +++ b/assets/webconfig/content/effects.html @@ -1,18 +1,14 @@
- +
-

Setting up a booteffect/color that is visible after Hyperion startup. Configure a background effect/color which is active, when all capture sources are disabled (also temporarily via Kodi Watch)

-
-
-
-
- +

Setting up a booteffect/color that is visible after Hyperion startup. Configure a background effect/color which is active, when all capture sources are disabled (also temporarily via Kodi Watch)

+
+
- diff --git a/assets/webconfig/content/effects_configurator.html b/assets/webconfig/content/effects_configurator.html index 998d7248..4e0dd90a 100644 --- a/assets/webconfig/content/effects_configurator.html +++ b/assets/webconfig/content/effects_configurator.html @@ -1,41 +1,47 @@
- +
-

Create out of the base effects new effects that are tuned to your liking. Depending on Effect there are options like color, speed, direction and more available.

-
+

Create out of the base effects new effects that are tuned to your liking. Depending on Effect there are options like color, speed, direction and more available.


-
+
+
+
- + -
-
+
ComponentStatusComponentStatus
+ + + + + + +
- +
+
- + +
+ +
+
+
+
+
+
+ + diff --git a/assets/webconfig/content/grabber.html b/assets/webconfig/content/grabber.html index e942d72b..4ac9ca33 100644 --- a/assets/webconfig/content/grabber.html +++ b/assets/webconfig/content/grabber.html @@ -2,16 +2,12 @@
- +
-

Hyperion supports two ways on how to get captured pictures for processing and output. The platform grabber which captures internal at the device you are running Hyperion on (best qualitiy) and the USB Grabber which gathers from a connected device the necessary pictures (more calibration work and configuration).

+

Hyperion supports two ways on how to get captured pictures for processing and output. The platform grabber which captures internal at the device you are running Hyperion on (best qualitiy) and the USB Grabber which gathers from a connected device the necessary pictures (more calibration work and configuration).

+
-
-
-
- -
- +
diff --git a/assets/webconfig/content/kodiconf.html b/assets/webconfig/content/kodiconf.html index 523c64b4..7db6f27a 100644 --- a/assets/webconfig/content/kodiconf.html +++ b/assets/webconfig/content/kodiconf.html @@ -1,23 +1,18 @@
- +
-

The Kodi Watcher enables you to enable and disable the screencapture depending on Kodi state. This is not limited to the same machine, you could observe also a Kodi on any other device at your network.

+

The Kodi Watcher enables you to enable and disable the screencapture depending on Kodi state. This is not limited to the same machine, you could observe also a Kodi on any other device at your network.

+
-
- -
-
- -
- +
- \ No newline at end of file + diff --git a/assets/webconfig/content/leds.html b/assets/webconfig/content/leds.html index 1d6e09bc..41624227 100644 --- a/assets/webconfig/content/leds.html +++ b/assets/webconfig/content/leds.html @@ -1,12 +1,3 @@ - - -
- +
-

The LED controller of youre choice is your way to output the led data via Raspberry PI GPIO, USB or network! Choose one, define your led layout and enjoy the light!

+

The LED controller of youre choice is your way to output the led data via Raspberry PI GPIO, USB or network! Choose one, define your led layout and enjoy the light!

+
-
+
-
-
- -