diff --git a/libsrc/leddevice/CMakeLists.txt b/libsrc/leddevice/CMakeLists.txt index 6bfc2fe8..608b1cb9 100644 --- a/libsrc/leddevice/CMakeLists.txt +++ b/libsrc/leddevice/CMakeLists.txt @@ -28,8 +28,7 @@ SET(Leddevice_HEADERS ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h ${CURRENT_SOURCE_DIR}/LedDeviceSedu.h ${CURRENT_SOURCE_DIR}/LedDeviceTest.h - ${CURRENT_SOURCE_DIR}/LedDeviceWs2812b.h - ${CURRENT_SOURCE_DIR}/LedDeviceWs2811.h + ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h ) SET(Leddevice_SOURCES @@ -44,8 +43,7 @@ SET(Leddevice_SOURCES ${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp ${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp ${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceWs2811.cpp - ${CURRENT_SOURCE_DIR}/LedDeviceWs2812b.cpp + ${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp ) if(ENABLE_SPIDEV) diff --git a/libsrc/leddevice/LedDeviceFactory.cpp b/libsrc/leddevice/LedDeviceFactory.cpp index 2a9aeb4e..855fe818 100644 --- a/libsrc/leddevice/LedDeviceFactory.cpp +++ b/libsrc/leddevice/LedDeviceFactory.cpp @@ -23,8 +23,7 @@ #include "LedDevicePiBlaster.h" #include "LedDeviceSedu.h" #include "LedDeviceTest.h" -#include "LedDeviceWs2811.h" -#include "LedDeviceWs2812b.h" +#include "LedDeviceHyperionUsbasp.h" LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) { @@ -87,23 +86,6 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) device = deviceWs2801; } #endif -// else if (type == "ws2811") -// { -// const std::string output = deviceConfig["output"].asString(); -// const std::string outputSpeed = deviceConfig["output"].asString(); -// const std::string timingOption = deviceConfig["timingOption"].asString(); - -// ws2811::SpeedMode speedMode = (outputSpeed == "high")? ws2811::highspeed : ws2811::lowspeed; -// if (outputSpeed != "high" && outputSpeed != "low") -// { -// std::cerr << "Incorrect speed-mode selected for WS2811: " << outputSpeed << " != {'high', 'low'}" << std::endl; -// } - -// LedDeviceWs2811 * deviceWs2811 = new LedDeviceWs2811(output, ws2811::fromString(timingOption, ws2811::option_2855), speedMode); -// deviceWs2811->open(); - -// device = deviceWs2811; -// } else if (type == "lightpack") { const std::string output = deviceConfig.get("output", "").asString(); @@ -147,18 +129,23 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig) device = deviceSedu; } + else if (type == "hyperion-usbasp-ws2801") + { + LedDeviceHyperionUsbasp * deviceHyperionUsbasp = new LedDeviceHyperionUsbasp(LedDeviceHyperionUsbasp::CMD_WRITE_WS2801); + deviceHyperionUsbasp->open(); + device = deviceHyperionUsbasp; + } + else if (type == "hyperion-usbasp-ws2812") + { + LedDeviceHyperionUsbasp * deviceHyperionUsbasp = new LedDeviceHyperionUsbasp(LedDeviceHyperionUsbasp::CMD_WRITE_WS2812); + deviceHyperionUsbasp->open(); + device = deviceHyperionUsbasp; + } else if (type == "test") { const std::string output = deviceConfig["output"].asString(); device = new LedDeviceTest(output); } - else if (type == "ws2812b") - { - LedDeviceWs2812b * deviceWs2812b = new LedDeviceWs2812b(); - deviceWs2812b->open(); - - device = deviceWs2812b; - } else { std::cout << "Unable to create device " << type << std::endl; diff --git a/libsrc/leddevice/LedDeviceHyperionUsbasp.cpp b/libsrc/leddevice/LedDeviceHyperionUsbasp.cpp new file mode 100644 index 00000000..9eddde90 --- /dev/null +++ b/libsrc/leddevice/LedDeviceHyperionUsbasp.cpp @@ -0,0 +1,205 @@ +// stl includes +#include +#include + +// Local Hyperion includes +#include "LedDeviceHyperionUsbasp.h" + +// Static constants which define the Hyperion Usbasp device +uint16_t LedDeviceHyperionUsbasp::_usbVendorId = 0x16c0; +uint16_t LedDeviceHyperionUsbasp::_usbProductId = 0x05dc; +std::string LedDeviceHyperionUsbasp::_usbProductDescription = "Hyperion led controller"; + + +LedDeviceHyperionUsbasp::LedDeviceHyperionUsbasp(uint8_t writeLedsCommand) : + LedDevice(), + _writeLedsCommand(writeLedsCommand), + _libusbContext(nullptr), + _deviceHandle(nullptr), + _ledCount(256) +{ +} + +LedDeviceHyperionUsbasp::~LedDeviceHyperionUsbasp() +{ + if (_deviceHandle != nullptr) + { + libusb_release_interface(_deviceHandle, 0); + libusb_attach_kernel_driver(_deviceHandle, 0); + libusb_close(_deviceHandle); + + _deviceHandle = nullptr; + } + + if (_libusbContext != nullptr) + { + libusb_exit(_libusbContext); + _libusbContext = nullptr; + } +} + +int LedDeviceHyperionUsbasp::open() +{ + int error; + + // initialize the usb context + if ((error = libusb_init(&_libusbContext)) != LIBUSB_SUCCESS) + { + std::cerr << "Error while initializing USB context(" << error << "): " << libusb_error_name(error) << std::endl; + _libusbContext = nullptr; + return -1; + } + //libusb_set_debug(_libusbContext, 3); + std::cout << "USB context initialized" << std::endl; + + // retrieve the list of usb devices + libusb_device ** deviceList; + ssize_t deviceCount = libusb_get_device_list(_libusbContext, &deviceList); + + // iterate the list of devices + for (ssize_t i = 0 ; i < deviceCount; ++i) + { + // try to open and initialize the device + error = testAndOpen(deviceList[i]); + + if (error == 0) + { + // a device was sucessfully opened. break from list + break; + } + } + + // free the device list + libusb_free_device_list(deviceList, 1); + + if (_deviceHandle == nullptr) + { + std::cerr << "No " << _usbProductDescription << " has been found" << std::endl; + } + + return _deviceHandle == nullptr ? -1 : 0; +} + +int LedDeviceHyperionUsbasp::testAndOpen(libusb_device * device) +{ + libusb_device_descriptor deviceDescriptor; + int error = libusb_get_device_descriptor(device, &deviceDescriptor); + if (error != LIBUSB_SUCCESS) + { + std::cerr << "Error while retrieving device descriptor(" << error << "): " << libusb_error_name(error) << std::endl; + return -1; + } + + if (deviceDescriptor.idVendor == _usbVendorId && + deviceDescriptor.idProduct == _usbProductId && + deviceDescriptor.iProduct != 0 && + getString(device, deviceDescriptor.iProduct) == _usbProductDescription) + { + // get the hardware address + int busNumber = libusb_get_bus_number(device); + int addressNumber = libusb_get_device_address(device); + + std::cout << _usbProductDescription << " found: bus=" << busNumber << " address=" << addressNumber << std::endl; + + try + { + _deviceHandle = openDevice(device); + std::cout << _usbProductDescription << " successfully opened" << std::endl; + return 0; + } + catch(int e) + { + _deviceHandle = nullptr; + std::cerr << "Unable to open " << _usbProductDescription << ". Searching for other device(" << e << "): " << libusb_error_name(e) << std::endl; + } + } + + return -1; +} + +int LedDeviceHyperionUsbasp::write(const std::vector &ledValues) +{ + _ledCount = ledValues.size(); + + int nbytes = libusb_control_transfer( + _deviceHandle, // device handle + LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, // request type + _writeLedsCommand, // request + 0, // value + 0, // index + (uint8_t *) ledValues.data(), // data + (3*_ledCount) & 0xffff, // length + 5000); // timeout + + // Disabling interupts for a little while on the device results in a PIPE error. All seems to keep functioning though... + if(nbytes < 0 && nbytes != LIBUSB_ERROR_PIPE) + { + std::cerr << "Error while writing data to " << _usbProductDescription << " (" << libusb_error_name(nbytes) << ")" << std::endl; + return -1; + } + + return 0; +} + +int LedDeviceHyperionUsbasp::switchOff() +{ + std::vector ledValues(_ledCount, ColorRgb::BLACK); + return write(ledValues); +} + +libusb_device_handle * LedDeviceHyperionUsbasp::openDevice(libusb_device *device) +{ + libusb_device_handle * handle = nullptr; + + int error = libusb_open(device, &handle); + if (error != LIBUSB_SUCCESS) + { + std::cerr << "unable to open device(" << error << "): " << libusb_error_name(error) << std::endl; + throw error; + } + + // detach kernel driver if it is active + if (libusb_kernel_driver_active(handle, 0) == 1) + { + error = libusb_detach_kernel_driver(handle, 0); + if (error != LIBUSB_SUCCESS) + { + std::cerr << "unable to detach kernel driver(" << error << "): " << libusb_error_name(error) << std::endl; + libusb_close(handle); + throw error; + } + } + + error = libusb_claim_interface(handle, 0); + if (error != LIBUSB_SUCCESS) + { + std::cerr << "unable to claim interface(" << error << "): " << libusb_error_name(error) << std::endl; + libusb_attach_kernel_driver(handle, 0); + libusb_close(handle); + throw error; + } + + return handle; +} + +std::string LedDeviceHyperionUsbasp::getString(libusb_device * device, int stringDescriptorIndex) +{ + libusb_device_handle * handle = nullptr; + + int error = libusb_open(device, &handle); + if (error != LIBUSB_SUCCESS) + { + throw error; + } + + char buffer[256]; + error = libusb_get_string_descriptor_ascii(handle, stringDescriptorIndex, reinterpret_cast(buffer), sizeof(buffer)); + if (error <= 0) + { + libusb_close(handle); + throw error; + } + + libusb_close(handle); + return std::string(buffer, error); +} diff --git a/libsrc/leddevice/LedDeviceHyperionUsbasp.h b/libsrc/leddevice/LedDeviceHyperionUsbasp.h new file mode 100644 index 00000000..a8f91cc7 --- /dev/null +++ b/libsrc/leddevice/LedDeviceHyperionUsbasp.h @@ -0,0 +1,88 @@ +#pragma once + +// stl includes +#include +#include +#include + +// libusb include +#include + +// Hyperion includes +#include + +/// +/// LedDevice implementation for a lightpack device (http://code.google.com/p/light-pack/) +/// +class LedDeviceHyperionUsbasp : public LedDevice +{ +public: + // Commands to the Device + enum Commands { + CMD_WRITE_WS2801 = 10, + CMD_WRITE_WS2812 = 11 + }; + + /// + /// Constructs the LedDeviceLightpack + /// + LedDeviceHyperionUsbasp(uint8_t writeLedsCommand); + + /// + /// Destructor of the LedDevice; closes the output device if it is open + /// + virtual ~LedDeviceHyperionUsbasp(); + + /// + /// Opens and configures the output device + /// + /// @return Zero on succes else negative + /// + int open(); + + /// + /// Writes the RGB-Color values to the leds. + /// + /// @param[in] ledValues The RGB-color per led + /// + /// @return Zero on success else negative + /// + virtual int write(const std::vector& ledValues); + + /// + /// Switch the leds off + /// + /// @return Zero on success else negative + /// + virtual int switchOff(); + +private: + /// + /// Test if the device is a Hyperion Usbasp device + /// + /// @return Zero on succes else negative + /// + int testAndOpen(libusb_device * device); + + static libusb_device_handle * openDevice(libusb_device * device); + + static std::string getString(libusb_device * device, int stringDescriptorIndex); + +private: + /// command to write the leds + const uint8_t _writeLedsCommand; + + /// libusb context + libusb_context * _libusbContext; + + /// libusb device handle + libusb_device_handle * _deviceHandle; + + /// Number of leds + int _ledCount; + + /// Usb device identifiers + static uint16_t _usbVendorId; + static uint16_t _usbProductId; + static std::string _usbProductDescription; +}; diff --git a/libsrc/leddevice/LedDeviceWs2811.cpp b/libsrc/leddevice/LedDeviceWs2811.cpp deleted file mode 100644 index 9fe0f8a3..00000000 --- a/libsrc/leddevice/LedDeviceWs2811.cpp +++ /dev/null @@ -1,182 +0,0 @@ - -// Local hyperion includes -#include "LedDeviceWs2811.h" - - -ws2811::SignalTiming ws2811::fromString(const std::string& signalTiming, const SignalTiming defaultValue) -{ - SignalTiming result = defaultValue; - if (signalTiming == "3755" || signalTiming == "option_3755") - { - result = option_3755; - } - else if (signalTiming == "3773" || signalTiming == "option_3773") - { - result = option_3773; - } - else if (signalTiming == "2855" || signalTiming == "option_2855") - { - result = option_2855; - } - else if (signalTiming == "2882" || signalTiming == "option_2882") - { - result = option_2882; - } - - return result; -} - -unsigned ws2811::getBaudrate(const SpeedMode speedMode) -{ - switch (speedMode) - { - case highspeed: - // Bit length: 125ns - return 8000000; - case lowspeed: - // Bit length: 250ns - return 4000000; - } - - return 0; -} -inline unsigned ws2811::getLength(const SignalTiming timing, const TimeOption option) -{ - switch (timing) - { - case option_3755: - // Reference: http://www.mikrocontroller.net/attachment/180459/WS2812B_preliminary.pdf - // Unit length: 125ns - switch (option) - { - case T0H: - return 3; // 400ns +-150ns - case T0L: - return 7; // 850ns +-150ns - case T1H: - return 7; // 800ns +-150ns - case T1L: - return 3; // 450ns +-150ns - } - case option_3773: - // Reference: www.adafruit.com/datasheets/WS2812.pdf‎ - // Unit length: 125ns - switch (option) - { - case T0H: - return 3; // 350ns +-150ns - case T0L: - return 7; // 800ns +-150ns - case T1H: - return 7; // 700ns +-150ns - case T1L: - return 3; // 600ns +-150ns - } - case option_2855: - // Reference: www.adafruit.com/datasheets/WS2811.pdf‎ - // Unit length: 250ns - switch (option) - { - case T0H: - return 2; // 500ns +-150ns - case T0L: - return 8; // 2000ns +-150ns - case T1H: - return 5; // 1200ns +-150ns - case T1L: - return 5; // 1300ns +-150ns - } - case option_2882: - // Reference: www.szparkson.net/download/WS2811.pdf‎ - // Unit length: 250ns - switch (option) - { - case T0H: - return 2; // 500ns +-150ns - case T0L: - return 8; // 2000ns +-150ns - case T1H: - return 8; // 2000ns +-150ns - case T1L: - return 2; // 500ns +-150ns - } - default: - std::cerr << "Unknown signal timing for ws2811: " << timing << std::endl; - } - return 0; -} - -uint8_t ws2811::bitToSignal(unsigned lenHigh) -{ - // Sanity check on the length of the 'high' signal - assert(0 < lenHigh && lenHigh < 10); - - uint8_t result = 0x00; - for (unsigned i=1; i & ledValues) -{ - if (_ledBuffer.size() != ledValues.size() * 3) - { - _ledBuffer.resize(ledValues.size() * 3); - } - - auto bufIt = _ledBuffer.begin(); - for (const ColorRgb & color : ledValues) - { - *bufIt = _byteToSignalTable[color.red ]; - ++bufIt; - *bufIt = _byteToSignalTable[color.green]; - ++bufIt; - *bufIt = _byteToSignalTable[color.blue ]; - ++bufIt; - } - - writeBytes(_ledBuffer.size() * 3, reinterpret_cast(_ledBuffer.data())); - - return 0; -} - -int LedDeviceWs2811::switchOff() -{ - write(std::vector(_ledBuffer.size()/3, ColorRgb::BLACK)); - return 0; -} - -void LedDeviceWs2811::fillEncodeTable(const ws2811::SignalTiming ledOption) -{ - _byteToSignalTable.resize(256); - for (unsigned byteValue=0; byteValue<256; ++byteValue) - { - const uint8_t byteVal = uint8_t(byteValue); - _byteToSignalTable[byteValue] = ws2811::translate(ledOption, byteVal); - } -} diff --git a/libsrc/leddevice/LedDeviceWs2811.h b/libsrc/leddevice/LedDeviceWs2811.h deleted file mode 100644 index 88edfceb..00000000 --- a/libsrc/leddevice/LedDeviceWs2811.h +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once - -// STL includes -#include - -// Local hyperion includes -#include "LedRs232Device.h" - -namespace ws2811 -{ - /// - /// Enumaration of known signal timings - /// - enum SignalTiming - { - option_3755, - option_3773, - option_2855, - option_2882, - not_a_signaltiming - }; - - /// - /// Enumaration of the possible speeds on which the ws2811 can operate. - /// - enum SpeedMode - { - lowspeed, - highspeed - }; - - /// - /// Enumeration of the signal 'parts' (T 0 high, T 1 high, T 0 low, T 1 low). - /// - enum TimeOption - { - T0H, - T1H, - T0L, - T1L - }; - - /// - /// Structure holding the signal for a signle byte - /// - struct ByteSignal - { - uint8_t bit_1; - uint8_t bit_2; - uint8_t bit_3; - uint8_t bit_4; - uint8_t bit_5; - uint8_t bit_6; - uint8_t bit_7; - uint8_t bit_8; - }; - // Make sure the structure is exatly the length we require - static_assert(sizeof(ByteSignal) == 8, "Incorrect sizeof ByteSignal (expected 8)"); - - /// - /// Translates a string to a signal timing - /// - /// @param signalTiming The string specifying the signal timing - /// @param defaultValue The default value (used if the string does not match any known timing) - /// - /// @return The SignalTiming (or not_a_signaltiming if it did not match) - /// - SignalTiming fromString(const std::string& signalTiming, const SignalTiming defaultValue); - - /// - /// Returns the required baudrate for a specific signal-timing - /// - /// @param SpeedMode The WS2811/WS2812 speed mode (WS2812b only has highspeed) - /// - /// @return The required baudrate for the signal timing - /// - unsigned getBaudrate(const SpeedMode speedMode); - - /// - /// The number of 'signal units' (bits) For the subpart of a specific timing scheme - /// - /// @param timing The controller option - /// @param option The signal part - /// - unsigned getLength(const SignalTiming timing, const TimeOption option); - - /// - /// Constructs a 'bit' based signal with defined 'high' length (and implicite defined 'low' - /// length. The signal is based on a 10bits bytes (incl. high startbit and low stopbit). The - /// total length of the high is given as parameter:
- /// lenHigh=7 => |-------|___| => 1 1111 1100 0 => 252 (start and stop bit are implicite) - /// - /// @param lenHigh The total length of the 'high' length (incl start-bit) - /// @return The byte representing the high-low signal - /// - uint8_t bitToSignal(unsigned lenHigh); - - /// - /// Translate a byte into signal levels for a specific WS2811 option - /// - /// @param ledOption The WS2811 configuration - /// @param byte The byte to translate - /// - /// @return The signal for the given byte (one byte per bit) - /// - ByteSignal translate(SignalTiming ledOption, uint8_t byte); -} - -class LedDeviceWs2811 : public LedRs232Device -{ -public: - /// - /// Constructs the LedDevice with Ws2811 attached via a serial port - /// - /// @param outputDevice The name of the output device (eg '/dev/ttyS0') - /// @param signalTiming The timing scheme used by the Ws2811 chip - /// @param speedMode The speed modus of the Ws2811 chip - /// - LedDeviceWs2811(const std::string& outputDevice, const ws2811::SignalTiming signalTiming, const ws2811::SpeedMode speedMode); - - /// - /// 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: - - /// - /// Fill the byte encoding table (_byteToSignalTable) for the specific timing option - /// - /// @param ledOption The timing option - /// - void fillEncodeTable(const ws2811::SignalTiming ledOption); - - /// Translation table of byte to signal/// - std::vector _byteToSignalTable; - - /// The buffer containing the packed RGB values - std::vector _ledBuffer; -}; diff --git a/libsrc/leddevice/LedDeviceWs2812b.cpp b/libsrc/leddevice/LedDeviceWs2812b.cpp deleted file mode 100644 index dd0bbb94..00000000 --- a/libsrc/leddevice/LedDeviceWs2812b.cpp +++ /dev/null @@ -1,96 +0,0 @@ - -// Linux includes -#include - -// Local Hyperion-Leddevice includes -#include "LedDeviceWs2812b.h" - -LedDeviceWs2812b::LedDeviceWs2812b() : - LedRs232Device("/dev/ttyUSB0", 2000000) -{ - // empty -} - -int LedDeviceWs2812b::write(const std::vector & ledValues) -{ - // Ensure the size of the led-buffer - if (_ledBuffer.size() != ledValues.size()*8) - { - _ledBuffer.resize(ledValues.size()*8, ~0x24); - } - - // Translate the channel of each color to a signal - uint8_t * signal_ptr = _ledBuffer.data(); - for (const ColorRgb & color : ledValues) - { - signal_ptr = color2signal(color, signal_ptr); - } - - const int result = writeBytes(_ledBuffer.size(), _ledBuffer.data()); - // Official latch time is 50us (lets give it 50us more) - usleep(100); - return result; -} - -uint8_t * LedDeviceWs2812b::color2signal(const ColorRgb & color, uint8_t * signal) -{ - *signal = bits2Signal(color.red & 0x80, color.red & 0x40, color.red & 0x20); - ++signal; - *signal = bits2Signal(color.red & 0x10, color.red & 0x08, color.red & 0x04); - ++signal; - *signal = bits2Signal(color.red & 0x02, color.green & 0x01, color.green & 0x80); - ++signal; - *signal = bits2Signal(color.green & 0x40, color.green & 0x20, color.green & 0x10); - ++signal; - *signal = bits2Signal(color.green & 0x08, color.green & 0x04, color.green & 0x02); - ++signal; - *signal = bits2Signal(color.green & 0x01, color.blue & 0x80, color.blue & 0x40); - ++signal; - *signal = bits2Signal(color.blue & 0x20, color.blue & 0x10, color.blue & 0x08); - ++signal; - *signal = bits2Signal(color.blue & 0x04, color.blue & 0x02, color.blue & 0x01); - ++signal; - - return signal; -} - -int LedDeviceWs2812b::switchOff() -{ - // Set all bytes in the signal buffer to zero - for (uint8_t & signal : _ledBuffer) - { - signal = ~0x24; - } - - return writeBytes(_ledBuffer.size(), _ledBuffer.data()); -} - -uint8_t LedDeviceWs2812b::bits2Signal(const bool bit_1, const bool bit_2, const bool bit_3) const -{ - // See https://github.com/tvdzwan/hyperion/wiki/Ws2812b for the explanation of the given - // translations - - // Bit index(default):1 2 3 - // | | | - // default value (1) 00 100 10 (0) - // - // Reversed value (1) 01 001 00 (0) - // | | | - // Bit index (rev): 3 2 1 - uint8_t result = 0x24; - - if(bit_1) - { - result |= 0x01; - } - if (bit_2) - { - result |= 0x08; - } - if (bit_3) - { - result |= 0x40; - } - - return ~result; -} diff --git a/libsrc/leddevice/LedDeviceWs2812b.h b/libsrc/leddevice/LedDeviceWs2812b.h deleted file mode 100644 index 6345a060..00000000 --- a/libsrc/leddevice/LedDeviceWs2812b.h +++ /dev/null @@ -1,60 +0,0 @@ - -#pragma once - -// Hyperion leddevice includes -#include "LedRs232Device.h" - -/// -/// The LedDevice for controlling a string of WS2812B leds. These are controlled over the mini-UART -/// of the RPi (/dev/ttyAMA0). -/// -class LedDeviceWs2812b : public LedRs232Device -{ -public: - /// - /// Constructs the device (all required parameters are hardcoded) - /// - LedDeviceWs2812b(); - - /// - /// Write the color data the the WS2812B led string - /// - /// @param ledValues The color data - /// @return Zero on succes else negative - /// - virtual int write(const std::vector & ledValues); - - /// - /// Write zero to all leds(that have been written by a previous write operation) - /// - /// @return Zero on succes else negative - /// - virtual int switchOff(); - -private: - - /// - /// Translate a color to the signal bits. The resulting bits are written to the given memory. - /// - /// @param color The color to translate - /// @param signal The pointer at the beginning of the signal to write - /// @return The pointer at the end of the written signal - /// - uint8_t * color2signal(const ColorRgb & color, uint8_t * signal); - - /// - /// Translates three bits to a single byte - /// - /// @param bit1 The value of the first bit (1=true, zero=false) - /// @param bit2 The value of the second bit (1=true, zero=false) - /// @param bit3 The value of the third bit (1=true, zero=false) - /// - /// @return The output-byte for the given two bit - /// - uint8_t bits2Signal(const bool bit1, const bool bit2, const bool bit3) const; - - /// - /// The output buffer for writing bytes to the output - /// - std::vector _ledBuffer; -}; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bd46d059..fa4b142b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -52,20 +52,3 @@ target_link_libraries(test_qregexp add_executable(test_qtscreenshot TestQtScreenshot.cpp) target_link_libraries(test_qtscreenshot ${QT_LIBRARIES}) - -add_executable(determineWs2811Timing DetermineWs2811Timing.cpp) - -add_executable(test_rs232highspeed - TestRs232HighSpeed.cpp - ../libsrc/leddevice/LedRs232Device.cpp - ../libsrc/leddevice/LedDeviceWs2812b.cpp) -target_link_libraries(test_rs232highspeed - serialport) - -if(NOT APPLE AND UNIX) - include_directories(/usr/include) - add_executable(test_uartHighSpeed TestUartHighSpeed.cpp) - - add_executable(test_nonUniformWs2812b TestNonUniformWs2812b.cpp) - add_executable(test_nonInvWs2812b TestNonInvWs2812b.cpp) -endif() diff --git a/test/DetermineWs2811Timing.cpp b/test/DetermineWs2811Timing.cpp deleted file mode 100644 index 1a47191a..00000000 --- a/test/DetermineWs2811Timing.cpp +++ /dev/null @@ -1,62 +0,0 @@ - -// STl includes -#include -#include - -bool requiredTiming(const int tHigh_ns, const int tLow_ns, const int error_ns, const int nrBits) -{ - std::cout << "=== " << nrBits << " bits case ===== " << std::endl; - double bitLength_ns = (tHigh_ns + tLow_ns)/double(nrBits); - double baudrate_Hz = 1.0 / bitLength_ns * 1e9; - std::cout << "Required bit length: " << bitLength_ns << "ns => baudrate = " << baudrate_Hz << std::endl; - - double highBitsExact = tHigh_ns/bitLength_ns; - int highBits = std::round(highBitsExact); - double lowBitsExact = tLow_ns/bitLength_ns; - int lowBits = std::round(lowBitsExact); - std::cout << "Bit division: high=" << highBits << "(" << highBitsExact << "); low=" << lowBits << "(" << lowBitsExact << ")" << std::endl; - - double highBitsError = std::fabs(highBitsExact - highBits); - double lowBitsError = std::fabs(highBitsExact - highBits); - double highError_ns = highBitsError * bitLength_ns; - double lowError_ns = lowBitsError * bitLength_ns; - - if (highError_ns > error_ns || lowError_ns > error_ns) - { - std::cerr << "Timing error outside specs: " << highError_ns << "; " << lowError_ns << " > " << error_ns << std::endl; - } - else - { - std::cout << "Timing within margins: " << highError_ns << "; " << lowError_ns << " < " << error_ns << std::endl; - } - - - - return true; -} - -int main() -{ - // 10bits - requiredTiming(400, 850, 150, 10); // Zero - requiredTiming(800, 450, 150, 10); // One - - // 6bits - requiredTiming(400, 850, 150, 6); // Zero - requiredTiming(800, 450, 150, 6); // One - - // 5bits - requiredTiming(400, 850, 150, 5); // Zero - requiredTiming(800, 450, 150, 5); // One - - requiredTiming(650, 600, 150, 5); // One - - // 4bits - requiredTiming(400, 850, 150, 4); // Zero - requiredTiming(800, 450, 150, 4); // One - - // 3bits - requiredTiming(400, 850, 150, 3); // Zero - requiredTiming(800, 450, 150, 3); // One - return 0; -} diff --git a/test/TestNonInvWs2812b.cpp b/test/TestNonInvWs2812b.cpp deleted file mode 100644 index 5db10dfb..00000000 --- a/test/TestNonInvWs2812b.cpp +++ /dev/null @@ -1,209 +0,0 @@ - -// 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); -void split(const uint8_t byte, uint8_t & out1, uint8_t & out2); -uint8_t encode(const bool bit1, const bool bit2, const bool bit3); - -void print(uint8_t byte) -{ - for (int i=0; i<8; ++i) - { - if (byte & (1 << i)) - { - std::cout << '1'; - } - else - { - std::cout << '0'; - } - } -} - -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() -{ - const std::vector data(9, 0x00); - std::vector encData = encode(data); - - for (uint8_t encByte : encData) - { - std::cout << "0 "; - print(encByte); - 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 = 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 int breakLength_ms = 1; - - encData = std::vector(128, 0x00); - - 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; -} - -std::vector encode(const std::vector & data) -{ - std::vector result; - - uint8_t previousByte = 0x00; - uint8_t nextByte = 0x00; - for (unsigned iData=0; iData> 4; -} - -uint8_t encode(const bool bit1, const bool bit2, const bool bit3) -{ - if (bit2) - { - uint8_t result = 0x19; // 0--1 01 10-1 - if (bit1) result |= 0x02; -// else result &= ~0x02; - - if (bit3) result |= 0x60; -// else result &= ~0x60; - - return result; - } - else - { - uint8_t result = 0x21;// 0x21 (0-10 01 0--1) - if (bit1) result |= 0x06; -// else result &= ~0x06; - - if (bit3) result |= 0x40; -// else result &= ~0x40; - - return result; - } -} diff --git a/test/TestNonUniformWs2812b.cpp b/test/TestNonUniformWs2812b.cpp deleted file mode 100644 index 97f14695..00000000 --- a/test/TestNonUniformWs2812b.cpp +++ /dev/null @@ -1,188 +0,0 @@ - -// 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, 0xff,0xff,0xff, 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()); - write(uart0_filestream, encData.data(), encData.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 -#include - -// Serialport includes -#include - -int testSerialPortLib(); -int testHyperionDevice(int argc, char** argv); -int testWs2812bDevice(); - -int main(int argc, char** argv) -{ -// if (argc == 1) -// { -// return testSerialPortLib(); -// } -// else -// { -// return testHyperionDevice(argc, argv); -// } - return testWs2812bDevice(); -} - -int testSerialPortLib() -{ - serial::Serial rs232Port("/dev/ttyAMA0", 4000000); - - std::default_random_engine generator; - std::uniform_int_distribution distribution(1,2); - - std::vector data; - for (int i=0; i<9; ++i) - { - int coinFlip = distribution(generator); - if (coinFlip == 1) - { - data.push_back(0xCE); - data.push_back(0xCE); - data.push_back(0xCE); - data.push_back(0xCE); - } - else - { - data.push_back(0x8C); - data.push_back(0x8C); - data.push_back(0x8C); - data.push_back(0x8C); - } - } - std::cout << "Type 'c' to continue, 'q' or 'x' to quit: "; - while (true) - { - char c = getchar(); - if (c == 'q' || c == 'x') - { - break; - } - if (c != 'c') - { - continue; - } - - rs232Port.flushOutput(); - rs232Port.write(data); - rs232Port.flush(); - - data.clear(); - for (int i=0; i<9; ++i) - { - int coinFlip = distribution(generator); - if (coinFlip == 1) - { - data.push_back(0xCE); - data.push_back(0xCE); - data.push_back(0xCE); - data.push_back(0xCE); - } - else - { - data.push_back(0x8C); - data.push_back(0x8C); - data.push_back(0x8C); - data.push_back(0x8C); - } - } - } - - try - { - - rs232Port.close(); - } - catch (const std::runtime_error& excp) - { - std::cout << "Caught exception: " << excp.what() << std::endl; - return -1; - } - - return 0; -} - -#include "../libsrc/leddevice/LedRs232Device.h" - -class TestDevice : public LedRs232Device -{ -public: - TestDevice() : - LedRs232Device("/dev/ttyAMA0", 4000000) - { - open(); - } - - int write(const std::vector &ledValues) - { - std::vector bytes(ledValues.size() * 3 * 4); - - uint8_t * bytePtr = bytes.data(); - for (ColorRgb color : ledValues) - { - byte2Signal(color.green, bytePtr); - bytePtr += 4; - byte2Signal(color.red, bytePtr); - bytePtr += 4; - byte2Signal(color.blue, bytePtr); - bytePtr += 4; - } - - writeBytes(bytes.size(), bytes.data()); - - return 0; - } - - int switchOff() { return 0; }; - - void writeTestSequence(const std::vector & data) - { - writeBytes(data.size(), data.data()); - } - - void byte2Signal(const uint8_t byte, uint8_t * output) - { - output[0] = bits2Signal(byte & 0x80, byte & 0x40); - output[1] = bits2Signal(byte & 0x20, byte & 0x10); - output[2] = bits2Signal(byte & 0x08, byte & 0x04); - output[3] = bits2Signal(byte & 0x02, byte & 0x01); - } - - uint8_t bits2Signal(const bool bit1, const bool bit2) - { - if (bit1) - { - if (bit2) - { - return 0x8C; - } - else - { - return 0xCC; - } - } - else - { - if (bit2) - { - return 0x8E; - } - else - { - return 0xCE; - } - } - - return 0x00; - } -}; - -int testHyperionDevice(int argc, char** argv) -{ - TestDevice rs232Device; - - if (argc > 1 && strncmp(argv[1], "off", 3) == 0) - { - rs232Device.write(std::vector(150, {0, 0, 0})); - return 0; - } - - - int loopCnt = 0; - - std::cout << "Type 'c' to continue, 'q' or 'x' to quit: "; - while (true) - { - char c = getchar(); - if (c == 'q' || c == 'x') - { - break; - } - if (c != 'c') - { - continue; - } - - rs232Device.write(std::vector(loopCnt, {255, 255, 255})); - - ++loopCnt; - } - - rs232Device.write(std::vector(150, {0, 0, 0})); - - return 0; -} - -#include "../libsrc/leddevice/LedDeviceWs2812b.h" - -#include - -int testWs2812bDevice() -{ - LedDeviceWs2812b device; - device.open(); - - std::cout << "Type 'c' to continue, 'q' or 'x' to quit: "; - int loopCnt = 0; - while (true) - { -// char c = getchar(); -// if (c == 'q' || c == 'x') -// { -// break; -// } -// if (c != 'c') -// { -// continue; -// } - - if (loopCnt%4 == 0) - device.write(std::vector(25, {255, 0, 0})); - else if (loopCnt%4 == 1) - device.write(std::vector(25, {0, 255, 0})); - else if (loopCnt%4 == 2) - device.write(std::vector(25, {0, 0, 255})); - else if (loopCnt%4 == 3) - device.write(std::vector(25, {17, 188, 66})); - - ++loopCnt; - - usleep(200000); - if (loopCnt > 200) - { - break; - } - } - - device.write(std::vector(150, {0, 0, 0})); - device.switchOff(); - - return 0; -} diff --git a/test/TestUartHighSpeed.cpp b/test/TestUartHighSpeed.cpp deleted file mode 100644 index 1a7b9440..00000000 --- a/test/TestUartHighSpeed.cpp +++ /dev/null @@ -1,387 +0,0 @@ - -#include -#include -#include -#include //Used for UART -#include //Used for UART -#include //Used for UART -#include - -#include - -#include -#include -#include -#include - -#include -#include - -void set_realtime_priority() { - int ret; - - // We'll operate on the currently running thread. - pthread_t this_thread = pthread_self(); - // struct sched_param is used to store the scheduling priority - struct sched_param params; - // We'll set the priority to the maximum. - params.sched_priority = sched_get_priority_max(SCHED_FIFO); - std::cout << "Trying to set thread realtime prio = " << params.sched_priority << std::endl; - - // Attempt to set thread real-time priority to the SCHED_FIFO policy - ret = pthread_setschedparam(this_thread, SCHED_FIFO, ¶ms); - if (ret != 0) { - // Print the error - std::cout << "Unsuccessful in setting thread realtime prio (erno=" << ret << ")" << std::endl; - return; - } - - // Now verify the change in thread priority - int policy = 0; - ret = pthread_getschedparam(this_thread, &policy, ¶ms); - if (ret != 0) { - std::cout << "Couldn't retrieve real-time scheduling paramers" << std::endl; - return; - } - - // Check the correct policy was applied - if(policy != SCHED_FIFO) { - std::cout << "Scheduling is NOT SCHED_FIFO!" << std::endl; - } else { - std::cout << "SCHED_FIFO OK" << std::endl; - } - - // Print thread scheduling priority - std::cout << "Thread priority is " << params.sched_priority << std::endl; -} - - -struct ColorSignal -{ - uint8_t green_1; - uint8_t green_2; - uint8_t green_3; - uint8_t green_4; - - uint8_t red_1; - uint8_t red_2; - uint8_t red_3; - uint8_t red_4; - - uint8_t blue_1; - uint8_t blue_2; - uint8_t blue_3; - uint8_t blue_4; -}; - -static ColorSignal RED_Signal = { 0xCE, 0xCE, 0xCE, 0xCE, - 0xCE, 0x8C, 0x8C, 0x8C, - 0xCE, 0xCE, 0xCE, 0xCE }; -static ColorSignal GREEN_Signal = { 0xCE, 0x8C, 0x8C, 0x8C, - 0xCE, 0xCE, 0xCE, 0xCE, - 0xCE, 0xCE, 0xCE, 0xCE }; -static ColorSignal BLUE_Signal = { 0xCE, 0xCE, 0xCE, 0xCE, - 0xCE, 0xCE, 0xCE, 0xCE, - 0xCE, 0x8C, 0x8C, 0x8C}; -static ColorSignal BLACK_Signal = { 0xCE, 0xCE, 0xCE, 0xCE, - 0xCE, 0xCE, 0xCE, 0xCE, - 0xCE, 0xCE, 0xCE, 0xCE}; - -static volatile bool _running; - -void signal_handler(int signum) -{ - _running = false; - -} - -void test3bitsEncoding(); - -int main() -{ - if (true) - { - test3bitsEncoding(); - return 0; - } - - _running = true; - signal(SIGTERM, &signal_handler); - - //------------------------- - //----- SETUP USART 0 ----- - //------------------------- - //At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively - int uart0_filestream = -1; - - //OPEN THE UART - //The flags (defined in fcntl.h): - // Access modes (use 1 of these): - // O_RDONLY - Open for reading only. - // O_RDWR - Open for reading and writing. - // O_WRONLY - Open for writing only. - // - // O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode. When set read requests on the file can return immediately with a failure status - // if there is no input immediately available (instead of blocking). Likewise, write requests can also return - // immediately with a failure status if the output can't be written immediately. - // - // O_NOCTTY - When set and path identifies a terminal device, open() shall not cause the terminal device to become the controlling terminal for the process. - uart0_filestream = open("/dev/ttyAMA0", O_WRONLY | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode - 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"); - } - -// if (0) - { - //CONFIGURE THE UART - //The flags (defined in /usr/include/termios.h - see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html): - // Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000 - // CSIZE:- CS5, CS6, CS7, CS8 - // CLOCAL - Ignore modem status lines - // CREAD - Enable receiver - // IGNPAR = Ignore characters with parity errors - // ICRNL - Map CR to NL on input (Use for ASCII comms where you want to auto correct end of line characters - don't use for bianry comms!) - // PARENB - Parity enable - // PARODD - Odd parity (else even) - struct termios options; - tcgetattr(uart0_filestream, &options); - options.c_cflag = B4000000 | CS8 | CLOCAL; // signalData(10, RED_Signal); - - int loopCnt = 0; - std::cout << "Type 'c' to continue, 'q' or 'x' to quit: "; - while (_running) - { - char c = getchar(); - if (c == 'q' || c == 'x') - { - break; - } - if (c != 'c') - { - continue; - } - - set_realtime_priority(); - for (int iRun=0; iRun<10; ++iRun) - { -// tcflush(uart0_filestream, TCOFLUSH); - write(uart0_filestream, signalData.data(), signalData.size()*sizeof(ColorSignal)); - tcdrain(uart0_filestream); - - usleep(100000); - ++loopCnt; - - if (loopCnt%3 == 2) - signalData = std::vector(10, GREEN_Signal); - else if(loopCnt%3 == 1) - signalData = std::vector(10, BLUE_Signal); - else if(loopCnt%3 == 0) - signalData = std::vector(10, RED_Signal); - - } - } - - signalData = std::vector(50, BLACK_Signal); - write(uart0_filestream, signalData.data(), signalData.size()*sizeof(ColorSignal)); - //----- CLOSE THE UART ----- - close(uart0_filestream); - - std::cout << "Program finished" << std::endl; - - return 0; -} - -std::vector bit3Encode(const std::vector & bytes); -uint8_t bit3Encode(const bool bit_1, const bool bit_2, const bool bit_3); - -void test3bitsEncoding() -{ - //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; - } - - // Configure the port - struct termios options; - tcgetattr(uart0_filestream, &options); - options.c_cflag = B2500000 | CS7 | CLOCAL; - options.c_iflag = IGNPAR; - options.c_oflag = 0; - options.c_lflag = 0; - - tcflush(uart0_filestream, TCIFLUSH); - tcsetattr(uart0_filestream, TCSANOW, &options); - - std::vector colorRed; - for (unsigned i=0; i<10; ++i) - { - colorRed.push_back(0x00); - colorRed.push_back(0xFF); - colorRed.push_back(0x00); - } - std::vector colorGreen; - for (unsigned i=0; i<10; ++i) - { - colorGreen.push_back(0xFF); - colorGreen.push_back(0x00); - colorGreen.push_back(0x00); - } - std::vector colorBlue; - for (unsigned i=0; i<10; ++i) - { - colorBlue.push_back(0x00); - colorBlue.push_back(0x00); - colorBlue.push_back(0xFF); - } - std::vector colorBlack; - for (unsigned i=0; i<10; ++i) - { - colorBlack.push_back(0x00); - colorBlack.push_back(0x00); - colorBlack.push_back(0x00); - } - const std::vector colorRedSignal = bit3Encode(colorRed); - const std::vector colorGreenSignal = bit3Encode(colorGreen); - const std::vector colorBlueSignal = bit3Encode(colorBlue); - const std::vector colorBlackSignal = bit3Encode(colorBlack); - - for (unsigned i=0; i<100; ++i) - { - size_t res; - res = write(uart0_filestream, colorRedSignal.data(), colorRedSignal.size()); - (void)res; - usleep(100000); - res = write(uart0_filestream, colorGreenSignal.data(), colorGreenSignal.size()); - (void)res; - usleep(100000); - res = write(uart0_filestream, colorBlueSignal.data(), colorBlueSignal.size()); - (void)res; - usleep(100000); - } - size_t res = write(uart0_filestream, colorBlackSignal.data(), colorBlackSignal.size()); - (void)res; - //----- CLOSE THE UART ----- - res = close(uart0_filestream); - (void)res; - - std::cout << "Program finished" << std::endl; -} - -std::vector bit3Encode(const std::vector & bytes) -{ - std::vector result; - - for (unsigned iByte=0; iByte