diff --git a/config/hyperion.config.json b/config/hyperion.config.json index 9af4ea5e..fa08d80d 100644 --- a/config/hyperion.config.json +++ b/config/hyperion.config.json @@ -348,10 +348,12 @@ ], /// The black border configuration, contains the following items: - /// * enable : true if the detector should be activated + /// * enable : true if the detector should be activated + /// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0) "blackborderdetector" : { - "enable" : true + "enable" : true, + "threshold" : 0.01 }, /// The configuration of the effect engine, contains the following items: diff --git a/config/hyperion_x86.config.json b/config/hyperion_x86.config.json index 89376b20..071713aa 100644 --- a/config/hyperion_x86.config.json +++ b/config/hyperion_x86.config.json @@ -13,9 +13,9 @@ "device" : { "name" : "MyPi", - "type" : "test", - "output" : "~/hyperion.test.out", - "rate" : 250000, + "type" : "adalight", + "output" : "/dev/ttyUSB0", + "rate" : 115200, "colorOrder" : "rgb" }, @@ -348,10 +348,12 @@ ], /// The black border configuration, contains the following items: - /// * enable : true if the detector should be activated + /// * enable : true if the detector should be activated + /// * threshold : Value below which a pixel is regarded as black (value between 0.0 and 1.0) "blackborderdetector" : { - "enable" : true + "enable" : true, + "threshold" : 0.01 }, /// The configuration of the effect engine, contains the following items: @@ -371,6 +373,38 @@ "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.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 + /// * grabScreensaver : Flag indicating that the frame-grabber is on(true) when XBMC is on screensaver + /// * enable3DDetection : Flag indicating that the frame-grabber should switch to a 3D compatible modus if a 3D video is playing +// "xbmcVideoChecker" : +// { +// "xbmcAddress" : "127.0.0.1", +// "xbmcTcpPort" : 9090, +// "grabVideo" : true, +// "grabPictures" : true, +// "grabAudio" : true, +// "grabMenu" : false, +// "grabScreensaver" : true, +// "enable3DDetection" : true +// }, + /// The configuration of the Json server which enables the json remote interface /// * port : Port at which the json server is started "jsonServer" : diff --git a/deploy/hyperion.deps.openelec-rpi.tar.gz.REMOVED.git-id b/deploy/hyperion.deps.openelec-rpi.tar.gz.REMOVED.git-id index 9fe8e9cc..8dfa8584 100644 --- a/deploy/hyperion.deps.openelec-rpi.tar.gz.REMOVED.git-id +++ b/deploy/hyperion.deps.openelec-rpi.tar.gz.REMOVED.git-id @@ -1 +1 @@ -4d50c38a61c9f32a15b29ef3b3953c2835fa9cac \ No newline at end of file +5e8ca7ba33eb38d828b50971ec94b045025caa78 \ No newline at end of file diff --git a/deploy/hyperion.tar.gz.REMOVED.git-id b/deploy/hyperion.tar.gz.REMOVED.git-id index 9770ad39..e41e5906 100644 --- a/deploy/hyperion.tar.gz.REMOVED.git-id +++ b/deploy/hyperion.tar.gz.REMOVED.git-id @@ -1 +1 @@ -69287788649383ba7926e315debc69b7f4bd82a0 \ No newline at end of file +2ad39031528c40c14e352cbc84784f48564cc59b \ No newline at end of file diff --git a/include/hyperion/BlackBorderDetector.h b/include/hyperion/BlackBorderDetector.h index c3393bdb..ce0bf25d 100644 --- a/include/hyperion/BlackBorderDetector.h +++ b/include/hyperion/BlackBorderDetector.h @@ -48,8 +48,9 @@ namespace hyperion public: /// /// Constructs a black-border detector + /// @param[in] blackborderThreshold The threshold which the blackborder detector should use /// - BlackBorderDetector(); + BlackBorderDetector(uint8_t blackborderThreshold); /// /// Performs the actual black-border detection on the given image @@ -125,7 +126,11 @@ namespace hyperion inline bool isBlack(const Pixel_T & color) { // Return the simple compare of the color against black - return color.red < 3 && color.green < 3 && color.green < 3; + return color.red < _blackborderThreshold && color.green < _blackborderThreshold && color.green < _blackborderThreshold; } + + private: + /// Threshold for the blackborder detector [0 .. 255] + const uint8_t _blackborderThreshold; }; } // end namespace hyperion diff --git a/include/hyperion/BlackBorderProcessor.h b/include/hyperion/BlackBorderProcessor.h index 3ec2fe42..4d0c4fca 100644 --- a/include/hyperion/BlackBorderProcessor.h +++ b/include/hyperion/BlackBorderProcessor.h @@ -21,11 +21,13 @@ namespace hyperion /// horizontal border becomes the current border /// @param blurRemoveCnt The size to add to a horizontal or vertical border (because the /// outer pixels is blurred (black and color combined due to image scaling)) + /// @param[in] blackborderThreshold The threshold which the blackborder detector should use /// BlackBorderProcessor( const unsigned unknownFrameCnt, const unsigned borderFrameCnt, - const unsigned blurRemoveCnt); + const unsigned blurRemoveCnt, + uint8_t blackborderThreshold); /// /// Return the current (detected) border diff --git a/include/hyperion/ImageProcessor.h b/include/hyperion/ImageProcessor.h index 6c4b4739..990b6593 100644 --- a/include/hyperion/ImageProcessor.h +++ b/include/hyperion/ImageProcessor.h @@ -53,7 +53,7 @@ public: verifyBorder(image); // Create a result vector and call the 'in place' functionl - std::vector colors = mImageToLeds->getMeanLedColor(image); + std::vector colors = _imageToLeds->getMeanLedColor(image); // return the computed colors return colors; @@ -75,7 +75,7 @@ public: verifyBorder(image); // Determine the mean-colors of each led (using the existing mapping) - mImageToLeds->getMeanLedColor(image, ledColors); + _imageToLeds->getMeanLedColor(image, ledColors); } /// @@ -98,8 +98,10 @@ private: /// given led-string specification /// /// @param[in] ledString The led-string specification + /// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled + /// @param[in] blackborderThreshold The threshold which the blackborder detector should use /// - ImageProcessor(const LedString &ledString, bool enableBlackBorderDetector); + ImageProcessor(const LedString &ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold); /// /// Performs black-border detection (if enabled) on the given image @@ -116,17 +118,17 @@ private: const hyperion::BlackBorder border = _borderProcessor->getCurrentBorder(); // Clean up the old mapping - delete mImageToLeds; + delete _imageToLeds; if (border.unknown) { // Construct a new buffer and mapping - mImageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), 0, 0, mLedString.leds()); + _imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), 0, 0, _ledString.leds()); } else { // Construct a new buffer and mapping - mImageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), border.horizontalSize, border.verticalSize, mLedString.leds()); + _imageToLeds = new hyperion::ImageToLedsMap(image.width(), image.height(), border.horizontalSize, border.verticalSize, _ledString.leds()); } std::cout << "CURRENT BORDER TYPE: unknown=" << border.unknown << " hor.size=" << border.horizontalSize << " vert.size=" << border.verticalSize << std::endl; @@ -135,14 +137,14 @@ private: private: /// The Led-string specification - const LedString mLedString; + const LedString _ledString; /// Flag the enables(true)/disabled(false) blackborder detector - bool _enableBlackBorderRemoval; + const bool _enableBlackBorderRemoval; /// The processor for black border detection hyperion::BlackBorderProcessor * _borderProcessor; /// The mapping of image-pixels to leds - hyperion::ImageToLedsMap* mImageToLeds; + hyperion::ImageToLedsMap* _imageToLeds; }; diff --git a/include/hyperion/ImageProcessorFactory.h b/include/hyperion/ImageProcessorFactory.h index a377bafa..cde64440 100644 --- a/include/hyperion/ImageProcessorFactory.h +++ b/include/hyperion/ImageProcessorFactory.h @@ -30,8 +30,10 @@ public: /// Initialises this factory with the given led-configuration /// /// @param[in] ledString The led configuration + /// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled + /// @param[in] blackborderThreshold The threshold which the blackborder detector should use /// - void init(const LedString& ledString, bool enableBlackBorderDetector); + void init(const LedString& ledString, bool enableBlackBorderDetector, double blackborderThreshold); /// /// Creates a new ImageProcessor. The onwership of the processor is transferred to the caller. @@ -46,4 +48,7 @@ private: /// Flag indicating if the black border detector should be used bool _enableBlackBorderDetector; + + /// Threshold for the blackborder detector [0 .. 255] + uint8_t _blackborderThreshold; }; diff --git a/libsrc/hyperion/BlackBorderDetector.cpp b/libsrc/hyperion/BlackBorderDetector.cpp index e86ba9ed..ed97bebe 100644 --- a/libsrc/hyperion/BlackBorderDetector.cpp +++ b/libsrc/hyperion/BlackBorderDetector.cpp @@ -4,7 +4,8 @@ using namespace hyperion; -BlackBorderDetector::BlackBorderDetector() +BlackBorderDetector::BlackBorderDetector(uint8_t blackborderThreshold) : + _blackborderThreshold(blackborderThreshold) { // empty } diff --git a/libsrc/hyperion/BlackBorderProcessor.cpp b/libsrc/hyperion/BlackBorderProcessor.cpp index 87ada03f..efc97724 100644 --- a/libsrc/hyperion/BlackBorderProcessor.cpp +++ b/libsrc/hyperion/BlackBorderProcessor.cpp @@ -4,14 +4,14 @@ using namespace hyperion; -BlackBorderProcessor::BlackBorderProcessor( - const unsigned unknownFrameCnt, +BlackBorderProcessor::BlackBorderProcessor(const unsigned unknownFrameCnt, const unsigned borderFrameCnt, - const unsigned blurRemoveCnt) : + const unsigned blurRemoveCnt, + uint8_t blackborderThreshold) : _unknownSwitchCnt(unknownFrameCnt), _borderSwitchCnt(borderFrameCnt), _blurRemoveCnt(blurRemoveCnt), - _detector(), + _detector(blackborderThreshold), _currentBorder({true, -1, -1}), _previousDetectedBorder({true, -1, -1}), _consistentCnt(0) diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index bfe14a9d..a81e4f3c 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -270,7 +270,10 @@ Hyperion::Hyperion(const Json::Value &jsonConfig) : throw std::runtime_error("Color transformation incorrectly set"); } // initialize the image processor factory - ImageProcessorFactory::getInstance().init(_ledString, jsonConfig["blackborderdetector"].get("enable", true).asBool()); + ImageProcessorFactory::getInstance().init( + _ledString, + jsonConfig["blackborderdetector"].get("enable", true).asBool(), + jsonConfig["blackborderdetector"].get("threshold", 0.01).asDouble()); // initialize the color smoothing filter _device = createColorSmoothing(jsonConfig["color"]["smoothing"], _device); diff --git a/libsrc/hyperion/ImageProcessor.cpp b/libsrc/hyperion/ImageProcessor.cpp index ec10f52c..cd39dd1e 100644 --- a/libsrc/hyperion/ImageProcessor.cpp +++ b/libsrc/hyperion/ImageProcessor.cpp @@ -6,46 +6,46 @@ using namespace hyperion; -ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector) : - mLedString(ledString), +ImageProcessor::ImageProcessor(const LedString& ledString, bool enableBlackBorderDetector, uint8_t blackborderThreshold) : + _ledString(ledString), _enableBlackBorderRemoval(enableBlackBorderDetector), - _borderProcessor(new BlackBorderProcessor(600, 50, 1)), - mImageToLeds(nullptr) + _borderProcessor(new BlackBorderProcessor(600, 50, 1, blackborderThreshold)), + _imageToLeds(nullptr) { // empty } ImageProcessor::~ImageProcessor() { - delete mImageToLeds; + delete _imageToLeds; delete _borderProcessor; } unsigned ImageProcessor::getLedCount() const { - return mLedString.leds().size(); + return _ledString.leds().size(); } void ImageProcessor::setSize(const unsigned width, const unsigned height) { // Check if the existing buffer-image is already the correct dimensions - if (mImageToLeds && mImageToLeds->width() == width && mImageToLeds->height() == height) + if (_imageToLeds && _imageToLeds->width() == width && _imageToLeds->height() == height) { return; } // Clean up the old buffer and mapping - delete mImageToLeds; + delete _imageToLeds; // Construct a new buffer and mapping - mImageToLeds = new ImageToLedsMap(width, height, 0, 0, mLedString.leds()); + _imageToLeds = new ImageToLedsMap(width, height, 0, 0, _ledString.leds()); } bool ImageProcessor::getScanParameters(size_t led, double &hscanBegin, double &hscanEnd, double &vscanBegin, double &vscanEnd) const { - if (led < mLedString.leds().size()) + if (led < _ledString.leds().size()) { - const Led & l = mLedString.leds()[led]; + const Led & l = _ledString.leds()[led]; hscanBegin = l.minX_frac; hscanEnd = l.maxX_frac; vscanBegin = l.minY_frac; diff --git a/libsrc/hyperion/ImageProcessorFactory.cpp b/libsrc/hyperion/ImageProcessorFactory.cpp index a5a7fb06..70987845 100644 --- a/libsrc/hyperion/ImageProcessorFactory.cpp +++ b/libsrc/hyperion/ImageProcessorFactory.cpp @@ -10,13 +10,25 @@ ImageProcessorFactory& ImageProcessorFactory::getInstance() return instance; } -void ImageProcessorFactory::init(const LedString& ledString, bool enableBlackBorderDetector) +void ImageProcessorFactory::init(const LedString& ledString, bool enableBlackBorderDetector, double blackborderThreshold) { _ledString = ledString; _enableBlackBorderDetector = enableBlackBorderDetector; + + int threshold = int(std::ceil(blackborderThreshold * 255)); + if (threshold < 0) + threshold = 0; + else if (threshold > 255) + threshold = 255; + _blackborderThreshold = uint8_t(threshold); + + if (_enableBlackBorderDetector) + { + std::cout << "Black border threshold set to " << blackborderThreshold << " (" << int(_blackborderThreshold) << ")" << std::endl; + } } ImageProcessor* ImageProcessorFactory::newImageProcessor() const { - return new ImageProcessor(_ledString, _enableBlackBorderDetector); + return new ImageProcessor(_ledString, _enableBlackBorderDetector, _blackborderThreshold); } diff --git a/libsrc/hyperion/hyperion.schema.json b/libsrc/hyperion/hyperion.schema.json index bd059aa4..38192312 100644 --- a/libsrc/hyperion/hyperion.schema.json +++ b/libsrc/hyperion/hyperion.schema.json @@ -223,6 +223,12 @@ "enable" : { "type" : "boolean", "required" : true + }, + "threshold" : { + "type" : "number", + "required" : false, + "minimum" : 0.0, + "maximum" : 1.0 } }, "additionalProperties" : false diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index 11504e36..6bfc2fe8 100644 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -54,6 +54,7 @@ if(ENABLE_SPIDEV) ${CURRENT_SOURCE_DIR}/LedSpiDevice.h ${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.h ${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.h + ${CURRENT_SOURCE_DIR}/LedDeviceP9813.h ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.h ) SET(Leddevice_SOURCES @@ -61,6 +62,7 @@ if(ENABLE_SPIDEV) ${CURRENT_SOURCE_DIR}/LedSpiDevice.cpp ${CURRENT_SOURCE_DIR}/LedDeviceLpd6803.cpp ${CURRENT_SOURCE_DIR}/LedDeviceLpd8806.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceP9813.cpp ${CURRENT_SOURCE_DIR}/LedDeviceWs2801.cpp ) endif(ENABLE_SPIDEV) diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 2f7b3a6b..e091da9e 100644 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -9,6 +9,7 @@ #ifdef ENABLE_SPIDEV #include "LedDeviceLpd6803.h" #include "LedDeviceLpd8806.h" + #include "LedDeviceP9813.h" #include "LedDeviceWs2801.h" #endif @@ -62,6 +63,16 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) device = deviceLpd8806; } + else if (type == "p9813") + { + const std::string output = deviceConfig["output"].asString(); + const unsigned rate = deviceConfig["rate"].asInt(); + + LedDeviceP9813* deviceP9813 = new LedDeviceP9813(output, rate); + deviceP9813->open(); + + device = deviceP9813; + } else if (type == "ws2801" || type == "lightberry") { const std::string output = deviceConfig["output"].asString(); diff --git a/libsrc/leddevice/LedDeviceP9813.cpp b/libsrc/leddevice/LedDeviceP9813.cpp new file mode 100644 index 00000000..752fc949 --- /dev/null +++ b/libsrc/leddevice/LedDeviceP9813.cpp @@ -0,0 +1,56 @@ + +// STL includes +#include +#include +#include + +// Linux includes +#include +#include + +// hyperion local includes +#include "LedDeviceP9813.h" + +LedDeviceP9813::LedDeviceP9813(const std::string& outputDevice, const unsigned baudrate) : + LedSpiDevice(outputDevice, baudrate, 0), + _ledCount(0) +{ + // empty +} + +int LedDeviceP9813::write(const std::vector &ledValues) +{ + if (_ledCount != ledValues.size()) + { + _ledBuf.resize(ledValues.size() * 4 + 8, 0x00); + _ledCount = ledValues.size(); + } + + uint8_t * dataPtr = _ledBuf.data(); + for (const ColorRgb & color : ledValues) + { + *dataPtr++ = calculateChecksum(color); + *dataPtr++ = color.blue; + *dataPtr++ = color.green; + *dataPtr++ = color.red; + } + + return writeBytes(_ledBuf.size(), _ledBuf.data()); +} + +int LedDeviceP9813::switchOff() +{ + return write(std::vector(_ledCount, ColorRgb{0,0,0})); +} + +uint8_t LedDeviceP9813::calculateChecksum(const ColorRgb & color) const +{ + uint8_t res = 0; + + res |= (uint8_t)0x03 << 6; + res |= (uint8_t)(~(color.blue >> 6) & 0x03) << 4; + res |= (uint8_t)(~(color.green >> 6) & 0x03) << 2; + res |= (uint8_t)(~(color.red >> 6) & 0x03); + + return res; +} diff --git a/libsrc/leddevice/LedDeviceP9813.h b/libsrc/leddevice/LedDeviceP9813.h new file mode 100644 index 00000000..ae70619f --- /dev/null +++ b/libsrc/leddevice/LedDeviceP9813.h @@ -0,0 +1,50 @@ +#pragma once + +// STL includes +#include + +// hyperion include +#include "LedSpiDevice.h" + +/// +/// Implementation of the LedDevice interface for writing to P9813 led device. +/// +class LedDeviceP9813 : public LedSpiDevice +{ +public: + /// + /// Constructs the LedDevice for a string containing leds of the type P9813 + /// + /// @param outputDevice The name of the output device (eg '/etc/SpiDev.0.0') + /// @param baudrate The used baudrate for writing to the output device + /// + LedDeviceP9813(const std::string& outputDevice, + const unsigned baudrate); + + /// + /// Writes the led color values to the led-device + /// + /// @param ledValues The color-value per led + /// @return Zero on succes else negative + /// + virtual int write(const std::vector &ledValues); + + /// Switch the leds off + virtual int switchOff(); + +private: + + /// the number of leds + size_t _ledCount; + + /// Buffer for writing/written led data + std::vector _ledBuf; + + /// + /// Calculates the required checksum for one led + /// + /// @param color The color of the led + /// @return The checksum for the led + /// + uint8_t calculateChecksum(const ColorRgb & color) const; +}; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 63751d1d..2ac4a4b3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -70,5 +70,6 @@ if(NOT APPLE AND UNIX) include_directories(/usr/include) add_executable(test_uartHighSpeed TestUartHighSpeed.cpp) - add_executable(test_nonInvWs2812b TestNonInvWs2812b.cpp) + add_executable(test_nonUniformWs2812b TestNonUniformWs2812b.cpp) + add_executable(test_nonInvWs2812b TestNonInvWs2812b.cpp) endif() diff --git a/test/TestBlackBorderDetector.cpp b/test/TestBlackBorderDetector.cpp index 8a92cba9..1d91079f 100644 --- a/test/TestBlackBorderDetector.cpp +++ b/test/TestBlackBorderDetector.cpp @@ -41,7 +41,7 @@ int TC_NO_BORDER() { int result = 0; - BlackBorderDetector detector; + BlackBorderDetector detector(3); { Image image = createImage(64, 64, 0, 0); @@ -60,7 +60,7 @@ int TC_TOP_BORDER() { int result = 0; - BlackBorderDetector detector; + BlackBorderDetector detector(3); { Image image = createImage(64, 64, 12, 0); @@ -79,7 +79,7 @@ int TC_LEFT_BORDER() { int result = 0; - BlackBorderDetector detector; + BlackBorderDetector detector(3); { Image image = createImage(64, 64, 0, 12); @@ -98,7 +98,7 @@ int TC_DUAL_BORDER() { int result = 0; - BlackBorderDetector detector; + BlackBorderDetector detector(3); { Image image = createImage(64, 64, 12, 12); @@ -116,7 +116,7 @@ int TC_UNKNOWN_BORDER() { int result = 0; - BlackBorderDetector detector; + BlackBorderDetector detector(3); { Image image = createImage(64, 64, 30, 30); diff --git a/test/TestBlackBorderProcessor.cpp b/test/TestBlackBorderProcessor.cpp index f5317f05..e0eef0d2 100644 --- a/test/TestBlackBorderProcessor.cpp +++ b/test/TestBlackBorderProcessor.cpp @@ -48,7 +48,7 @@ int main() unsigned borderCnt = 50; unsigned blurCnt = 0; - BlackBorderProcessor processor(unknownCnt, borderCnt, blurCnt); + BlackBorderProcessor processor(unknownCnt, borderCnt, blurCnt, 3); // Start with 'no border' detection Image noBorderImage = createImage(64, 64, 0, 0); diff --git a/test/TestNonInvWs2812b.cpp b/test/TestNonInvWs2812b.cpp index 05d60b39..269c9d27 100644 --- a/test/TestNonInvWs2812b.cpp +++ b/test/TestNonInvWs2812b.cpp @@ -4,6 +4,11 @@ #include #include +#include //Used for UART +#include //Used for UART +#include //Used for UART +#include + std::vector encode(const std::vector & data); void split(const uint8_t byte, uint8_t & out1, uint8_t & out2); uint8_t encode(const bool bit1, const bool bit2, const bool bit3); @@ -23,10 +28,41 @@ void print(uint8_t byte) } } +void printClockSignal(const std::vector & signal) +{ + bool prevBit = true; + bool nextBit = true; + + for (uint8_t byte : signal) + { + + for (int i=-1; i<9; ++i) + { + if (i == -1) // Start bit + nextBit = false; + else if (i == 8) // Stop bit + nextBit = true; + else + nextBit = byte & (1 << i); + + if (!prevBit && nextBit) + { + std::cout << ' '; + } + + if (nextBit) + std::cout << '1'; + else + std::cout << '0'; + + prevBit = nextBit; + } + } +} + int main() { - std::vector data(3, 0x55); - + const std::vector data(9, 0xff); std::vector encData = encode(data); for (uint8_t encByte : encData) @@ -36,7 +72,45 @@ int main() std::cout << " 1"; } std::cout << std::endl; + printClockSignal(encData); + std::cout << std::endl; + //OPEN THE UART +// int uart0_filestream = open("/dev/ttyAMA0", O_WRONLY | O_NOCTTY | O_NDELAY); + int uart0_filestream = open("/dev/ttyUSB0", O_WRONLY | O_NOCTTY | O_NDELAY); + if (uart0_filestream == -1) + { + //ERROR - CAN'T OPEN SERIAL PORT + printf("Error - Unable to open UART. Ensure it is not in use by another application\n"); + return -1; + } + + // Configure the port + struct termios options; + tcgetattr(uart0_filestream, &options); + options.c_cflag = B4000000 | CS8 | CLOCAL; + options.c_iflag = IGNPAR; + options.c_oflag = 0; + options.c_lflag = 0; + + tcflush(uart0_filestream, TCIFLUSH); + tcsetattr(uart0_filestream, TCSANOW, &options); + + char c = getchar(); + + const int breakLength_ms = 1; + + encData = std::vector(128, 0x10); + + write(uart0_filestream, encData.data(), encData.size()); + + tcsendbreak(uart0_filestream, breakLength_ms); + + //tcdrain(uart0_filestream); +// res = write(uart0_filestream, encData.data(), encData.size()); +// (void)res; + + close(uart0_filestream); return 0; } @@ -96,19 +170,16 @@ std::vector encode(const std::vector & data) previousByte = nextByte; } + result.push_back(previousByte); + + return result; } void split(const uint8_t byte, uint8_t & out1, uint8_t & out2) { - print(byte); std::cout << " => "; - print(out2); std::cout << " => "; - out1 &= ~0x0F; out1 |= (byte & 0x0F) << 4; -// out2 &= ~0xF0; - print(out2); std::cout << " => "; out2 = (byte & 0xF0) >> 4; - print(out2); std::cout << std::endl; } uint8_t encode(const bool bit1, const bool bit2, const bool bit3) diff --git a/test/TestNonUniformWs2812b.cpp b/test/TestNonUniformWs2812b.cpp new file mode 100644 index 00000000..0a15339d --- /dev/null +++ b/test/TestNonUniformWs2812b.cpp @@ -0,0 +1,186 @@ + +// STL includes +#include +#include +#include + +#include //Used for UART +#include //Used for UART +#include //Used for UART +#include + +std::vector encode(const std::vector & data); +uint8_t encode(const bool bit1, const bool bit2, const bool bit3); + +void printClockSignal(const std::vector & signal) +{ + bool prevBit = true; + bool nextBit = true; + + for (uint8_t byte : signal) + { + + for (int i=-1; i<9; ++i) + { + if (i == -1) // Start bit + nextBit = true; + else if (i == 8) // Stop bit + nextBit = false; + else + nextBit = ~byte & (1 << i); + + if (!prevBit && nextBit) + { + std::cout << ' '; + } + + if (nextBit) + std::cout << '1'; + else + std::cout << '0'; + + prevBit = nextBit; + } + } +} + +int main() +{ + const std::vector white{0xff, 0xff, 0xff}; + const std::vector green{0xff, 0x00, 0x00}; + const std::vector red {0x00, 0xff, 0x00}; + const std::vector blue {0x00, 0x00, 0xff}; + const std::vector cyan {0xff, 0x00, 0xff}; + const std::vector mix {0x55, 0x55, 0x55}; + const std::vector black{0x00, 0x00, 0x00}; + const std::vector gray{0x01, 0x01, 0x01}; + +// printClockSignal(encode(mix));std::cout << std::endl; + + //OPEN THE UART +// int uart0_filestream = open("/dev/ttyAMA0", O_WRONLY | O_NOCTTY | O_NDELAY); + int uart0_filestream = open("/dev/ttyUSB0", O_WRONLY | O_NOCTTY | O_NDELAY); + if (uart0_filestream == -1) + { + //ERROR - CAN'T OPEN SERIAL PORT + printf("Error - Unable to open UART. Ensure it is not in use by another application\n"); + return -1; + } + + // Configure the port + struct termios options; + tcgetattr(uart0_filestream, &options); + options.c_cflag = B2500000 | CS8 | CLOCAL; + options.c_iflag = IGNPAR; + options.c_oflag = 0; + options.c_lflag = 0; + + tcflush(uart0_filestream, TCIFLUSH); + tcsetattr(uart0_filestream, TCSANOW, &options); + + { + getchar(); + const std::vector encGreenData = encode(green); + const std::vector encBlueData = encode(blue); + const std::vector encRedData = encode(red); + const std::vector encGrayData = encode(gray); + const std::vector encBlackData = encode(black); + + //std::cout << "Writing GREEN ("; printClockSignal(encode(green)); std::cout << ")" << std::endl; + const std::vector garbage {0x0f}; + write(uart0_filestream, garbage.data(), garbage.size()); + write(uart0_filestream, encGreenData.data(), encGreenData.size()); + write(uart0_filestream, encRedData.data(), encRedData.size()); + write(uart0_filestream, encBlueData.data(), encBlueData.size()); + write(uart0_filestream, encGrayData.data(), encGrayData.size()); + write(uart0_filestream, encBlackData.data(), encBlackData.size()); + } + { + getchar(); + const std::vector encData = encode(white); + std::cout << "Writing WHITE ("; printClockSignal(encode(white)); std::cout << ")" << std::endl; + const std::vector garbage {0x0f}; + write(uart0_filestream, garbage.data(), garbage.size()); + write(uart0_filestream, encData.data(), encData.size()); + } + { + getchar(); + const std::vector encData = encode(green); + std::cout << "Writing GREEN ("; printClockSignal(encode(green)); std::cout << ")" << std::endl; + write(uart0_filestream, encData.data(), encData.size()); + } + { + getchar(); + const std::vector encData = encode(red); + std::cout << "Writing RED ("; printClockSignal(encode(red)); std::cout << ")" << std::endl; + write(uart0_filestream, encData.data(), encData.size()); + } + { + getchar(); + const std::vector encData = encode(blue); + std::cout << "Writing BLUE ("; printClockSignal(encode(blue)); std::cout << ")" << std::endl; + write(uart0_filestream, encData.data(), encData.size()); + } + { + getchar(); + const std::vector encData = encode(cyan); + std::cout << "Writing CYAN? ("; printClockSignal(encode(cyan)); std::cout << ")" << std::endl; + write(uart0_filestream, encData.data(), encData.size()); + } + { + getchar(); + const std::vector encData = encode(mix); + std::cout << "Writing MIX ("; printClockSignal(encode(mix)); std::cout << ")" << std::endl; + write(uart0_filestream, encData.data(), encData.size()); + } + { + getchar(); + const std::vector encData = encode(black); + std::cout << "Writing BLACK ("; printClockSignal(encode(black)); std::cout << ")" << std::endl; + write(uart0_filestream, encData.data(), encData.size()); + write(uart0_filestream, encData.data(), encData.size()); + write(uart0_filestream, encData.data(), encData.size()); + write(uart0_filestream, encData.data(), encData.size()); + } + + close(uart0_filestream); + + return 0; +} + +std::vector encode(const std::vector & data) +{ + std::vector result; + for (size_t iByte=0; iByte