diff --git a/libsrc/leddevice/LedDeviceWs2812b.cpp b/libsrc/leddevice/LedDeviceWs2812b.cpp index 98750103..4025aa31 100644 --- a/libsrc/leddevice/LedDeviceWs2812b.cpp +++ b/libsrc/leddevice/LedDeviceWs2812b.cpp @@ -1,4 +1,7 @@ +// Linux includes +#include + // Local Hyperion-Leddevice includes #include "LedDeviceWs2812b.h" @@ -17,15 +20,19 @@ int LedDeviceWs2812b::write(const std::vector & ledValues) } // Translate the channel of each color to a signal - auto bufIt = _ledBuffer.begin(); - for (const ColorRgb& color : ledValues) + for (unsigned iLed=0; iLed(_ledBuffer.data())); + const int result = writeBytes(_ledBuffer.size()*sizeof(ByteSignal), reinterpret_cast(_ledBuffer.data())); + // Official latch time is 50us (lets give it 50us more) + usleep(100); + return result; } int LedDeviceWs2812b::switchOff() @@ -63,14 +70,29 @@ uint8_t LedDeviceWs2812b::bits2Signal(const bool bit1, const bool bit2) const { // See https://github.com/tvdzwan/hyperion/wiki/Ws2812b for the explanation of the given // translations + + // Encoding scheme 1 + // 00 1 1000 1100 0 1 0111 0011 0 1 1100 1110 0 0xCE + // 01 1 1000 1110 0 1 0111 0001 0 1 1000 1110 0 0x8E + // 10 1 1100 1100 0 1 0011 0011 0 1 1100 1100 0 0xCC + // 11 1 1100 1110 0 1 0011 0001 0 1 1000 1100 0 0x8C + + // Encoding schem 2 + // 00 - 1 0000 1000 0 - 1 1111 0111 0 - 1 1110 1111 0 - 0xEF + // 01 - 1 0000 1111 0 - 1 1111 0000 0 - 1 0000 1111 0 - 0x0F + // 10 - 1 1110 1000 0 - 1 0001 0111 0 - 1 1110 1000 0 - 0xE8 + // 11 - 1 1110 1111 0 - 1 0001 0000 0 - 1 0000 1000 0 - 0x08 + if (bit1) { if (bit2) { +// return 0x08; return 0x8C; } else { +// return 0xE8; return 0xCC; } } @@ -78,10 +100,12 @@ uint8_t LedDeviceWs2812b::bits2Signal(const bool bit1, const bool bit2) const { if (bit2) { +// return 0x0F; return 0x8E; } else { +// return 0xEF; return 0xCE; } } diff --git a/libsrc/leddevice/LedRs232Device.cpp b/libsrc/leddevice/LedRs232Device.cpp index 476861b8..ab289d78 100644 --- a/libsrc/leddevice/LedRs232Device.cpp +++ b/libsrc/leddevice/LedRs232Device.cpp @@ -57,6 +57,7 @@ int LedRs232Device::writeBytes(const unsigned size, const uint8_t * data) try { + _rs232Port.flushOutput(); _rs232Port.write(data, size); _rs232Port.flush(); } diff --git a/test/DetermineWs2811Timing.cpp b/test/DetermineWs2811Timing.cpp index 3b4c5f25..1a47191a 100644 --- a/test/DetermineWs2811Timing.cpp +++ b/test/DetermineWs2811Timing.cpp @@ -49,6 +49,8 @@ int main() 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 diff --git a/test/TestRs232HighSpeed.cpp b/test/TestRs232HighSpeed.cpp index 16c48be0..c7d68d17 100644 --- a/test/TestRs232HighSpeed.cpp +++ b/test/TestRs232HighSpeed.cpp @@ -62,7 +62,9 @@ int testSerialPortLib() continue; } + rs232Port.flushOutput(); rs232Port.write(data); + rs232Port.flush(); data.clear(); for (int i=0; i<9; ++i) diff --git a/test/TestUartHighSpeed.cpp b/test/TestUartHighSpeed.cpp index 922dc885..1fc0b9bb 100644 --- a/test/TestUartHighSpeed.cpp +++ b/test/TestUartHighSpeed.cpp @@ -12,8 +12,80 @@ #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; @@ -46,7 +118,7 @@ int main() // 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_RDWR | O_NOCTTY | O_NDELAY); //Open in non blocking read/write mode + 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 @@ -67,17 +139,18 @@ int main() // PARODD - Odd parity (else even) struct termios options; tcgetattr(uart0_filestream, &options); - options.c_cflag = B4000000 | CS8 | CLOCAL | CREAD; //) (*txIt) << " 0 "; - } - std::cout << "]" << std::endl; + std::vector signalData(10, RED_Signal); + int loopCnt = 0; std::cout << "Type 'c' to continue, 'q' or 'x' to quit: "; while (_running) { @@ -182,38 +217,28 @@ int main() continue; } - int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0])); //Filestream, bytes to write, number of bytes to write - if (count < 0) + set_realtime_priority(); + for (int iRun=0; iRun<10; ++iRun) { - std::cerr << "UART TX error" << std::endl; +// tcflush(uart0_filestream, TCOFLUSH); + write(uart0_filestream, signalData.data(), signalData.size()*sizeof(ColorSignal)); + tcdrain(uart0_filestream); - //----- CLOSE THE UART ----- - close(uart0_filestream); - return -1; - } - std::cout << "Writing " << count << " bytes to uart" << std::endl; + 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); - p_tx_buffer = &tx_buffer[0]; - for (int i=0; i<9; ++i) - { - int coinFlip = distribution(generator); - if (coinFlip == 1) - { - *p_tx_buffer++ = 0xCE; - *p_tx_buffer++ = 0xCE; - *p_tx_buffer++ = 0xCE; - *p_tx_buffer++ = 0xCE; - } - else - { - *p_tx_buffer++ = 0x8C; - *p_tx_buffer++ = 0x8C; - *p_tx_buffer++ = 0x8C; - *p_tx_buffer++ = 0x8C; - } } } + signalData = std::vector(50, BLACK_Signal); + write(uart0_filestream, signalData.data(), signalData.size()*sizeof(ColorSignal)); //----- CLOSE THE UART ----- close(uart0_filestream);