mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Modification and additions to test working of ws2812b
Former-commit-id: 2a7eb3cb67c85a4a4042bd0f1a6ea4d58792b1c2
This commit is contained in:
parent
eaa4b0bae5
commit
71b8fd4879
@ -1,4 +1,7 @@
|
|||||||
|
|
||||||
|
// Linux includes
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
// Local Hyperion-Leddevice includes
|
// Local Hyperion-Leddevice includes
|
||||||
#include "LedDeviceWs2812b.h"
|
#include "LedDeviceWs2812b.h"
|
||||||
|
|
||||||
@ -17,15 +20,19 @@ int LedDeviceWs2812b::write(const std::vector<ColorRgb> & ledValues)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Translate the channel of each color to a signal
|
// Translate the channel of each color to a signal
|
||||||
auto bufIt = _ledBuffer.begin();
|
for (unsigned iLed=0; iLed<ledValues.size(); ++iLed)
|
||||||
for (const ColorRgb& color : ledValues)
|
|
||||||
{
|
{
|
||||||
*bufIt++ = _byte2signalTable[color.red];
|
const ColorRgb & color = ledValues[iLed];
|
||||||
*bufIt++ = _byte2signalTable[color.green];
|
|
||||||
*bufIt++ = _byte2signalTable[color.blue];
|
_ledBuffer[3*iLed] = _byte2signalTable[color.red];
|
||||||
|
_ledBuffer[3*iLed + 1] = _byte2signalTable[color.green];
|
||||||
|
_ledBuffer[3*iLed + 2] = _byte2signalTable[color.blue];
|
||||||
}
|
}
|
||||||
|
|
||||||
return writeBytes(_ledBuffer.size()*sizeof(ByteSignal), reinterpret_cast<uint8_t *>(_ledBuffer.data()));
|
const int result = writeBytes(_ledBuffer.size()*sizeof(ByteSignal), reinterpret_cast<uint8_t *>(_ledBuffer.data()));
|
||||||
|
// Official latch time is 50us (lets give it 50us more)
|
||||||
|
usleep(100);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LedDeviceWs2812b::switchOff()
|
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
|
// See https://github.com/tvdzwan/hyperion/wiki/Ws2812b for the explanation of the given
|
||||||
// translations
|
// 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 (bit1)
|
||||||
{
|
{
|
||||||
if (bit2)
|
if (bit2)
|
||||||
{
|
{
|
||||||
|
// return 0x08;
|
||||||
return 0x8C;
|
return 0x8C;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// return 0xE8;
|
||||||
return 0xCC;
|
return 0xCC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,10 +100,12 @@ uint8_t LedDeviceWs2812b::bits2Signal(const bool bit1, const bool bit2) const
|
|||||||
{
|
{
|
||||||
if (bit2)
|
if (bit2)
|
||||||
{
|
{
|
||||||
|
// return 0x0F;
|
||||||
return 0x8E;
|
return 0x8E;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// return 0xEF;
|
||||||
return 0xCE;
|
return 0xCE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,7 @@ int LedRs232Device::writeBytes(const unsigned size, const uint8_t * data)
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
_rs232Port.flushOutput();
|
||||||
_rs232Port.write(data, size);
|
_rs232Port.write(data, size);
|
||||||
_rs232Port.flush();
|
_rs232Port.flush();
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,8 @@ int main()
|
|||||||
requiredTiming(400, 850, 150, 5); // Zero
|
requiredTiming(400, 850, 150, 5); // Zero
|
||||||
requiredTiming(800, 450, 150, 5); // One
|
requiredTiming(800, 450, 150, 5); // One
|
||||||
|
|
||||||
|
requiredTiming(650, 600, 150, 5); // One
|
||||||
|
|
||||||
// 4bits
|
// 4bits
|
||||||
requiredTiming(400, 850, 150, 4); // Zero
|
requiredTiming(400, 850, 150, 4); // Zero
|
||||||
requiredTiming(800, 450, 150, 4); // One
|
requiredTiming(800, 450, 150, 4); // One
|
||||||
|
@ -62,7 +62,9 @@ int testSerialPortLib()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rs232Port.flushOutput();
|
||||||
rs232Port.write(data);
|
rs232Port.write(data);
|
||||||
|
rs232Port.flush();
|
||||||
|
|
||||||
data.clear();
|
data.clear();
|
||||||
for (int i=0; i<9; ++i)
|
for (int i=0; i<9; ++i)
|
||||||
|
@ -12,8 +12,80 @@
|
|||||||
#include <csignal>
|
#include <csignal>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <QElapsedTimer>
|
#include <pthread.h>
|
||||||
|
#include <sched.h>
|
||||||
|
|
||||||
|
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;
|
static volatile bool _running;
|
||||||
|
|
||||||
@ -46,7 +118,7 @@ int main()
|
|||||||
// immediately with a failure status if the output can't be written immediately.
|
// 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.
|
// 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)
|
if (uart0_filestream == -1)
|
||||||
{
|
{
|
||||||
//ERROR - CAN'T OPEN SERIAL PORT
|
//ERROR - CAN'T OPEN SERIAL PORT
|
||||||
@ -67,17 +139,18 @@ int main()
|
|||||||
// PARODD - Odd parity (else even)
|
// PARODD - Odd parity (else even)
|
||||||
struct termios options;
|
struct termios options;
|
||||||
tcgetattr(uart0_filestream, &options);
|
tcgetattr(uart0_filestream, &options);
|
||||||
options.c_cflag = B4000000 | CS8 | CLOCAL | CREAD; //<Set baud rate
|
options.c_cflag = B4000000 | CS8 | CLOCAL; //<Set baud rate
|
||||||
options.c_iflag = IGNPAR;
|
options.c_iflag = IGNPAR;
|
||||||
options.c_oflag = 0;
|
options.c_oflag = 0;
|
||||||
options.c_lflag = 0;
|
options.c_lflag = 0;
|
||||||
tcflush(uart0_filestream, TCIFLUSH);
|
cfmakeraw(&options);
|
||||||
|
|
||||||
std::cout << "options.c_cflag = " << options.c_cflag << std::endl;
|
std::cout << "options.c_cflag = " << options.c_cflag << std::endl;
|
||||||
std::cout << "options.c_iflag = " << options.c_iflag << std::endl;
|
std::cout << "options.c_iflag = " << options.c_iflag << std::endl;
|
||||||
std::cout << "options.c_oflag = " << options.c_oflag << std::endl;
|
std::cout << "options.c_oflag = " << options.c_oflag << std::endl;
|
||||||
std::cout << "options.c_lflag = " << options.c_lflag << std::endl;
|
std::cout << "options.c_lflag = " << options.c_lflag << std::endl;
|
||||||
|
|
||||||
|
tcflush(uart0_filestream, TCIFLUSH);
|
||||||
tcsetattr(uart0_filestream, TCSANOW, &options);
|
tcsetattr(uart0_filestream, TCSANOW, &options);
|
||||||
// Let's verify configured options
|
// Let's verify configured options
|
||||||
tcgetattr(uart0_filestream, &options);
|
tcgetattr(uart0_filestream, &options);
|
||||||
@ -128,47 +201,9 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----- TX BYTES -----
|
//----- TX BYTES -----
|
||||||
uint8_t tx_buffer[3*3*8*4];
|
std::vector<ColorSignal> signalData(10, RED_Signal);
|
||||||
uint8_t *p_tx_buffer;
|
|
||||||
|
|
||||||
// for (int i=0; i<3; ++i)
|
|
||||||
// {
|
|
||||||
// Writing 0xFF, 0x00, 0x00
|
|
||||||
// *p_tx_buffer++ = 0x8C;
|
|
||||||
// *p_tx_buffer++ = 0x8C;
|
|
||||||
// *p_tx_buffer++ = 0x8C;
|
|
||||||
// *p_tx_buffer++ = 0x8C;
|
|
||||||
|
|
||||||
std::default_random_engine generator;
|
|
||||||
std::uniform_int_distribution<int> distribution(1,2);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Binary stream: [";
|
|
||||||
for (unsigned char* txIt=&(tx_buffer[0]); txIt!=p_tx_buffer; ++txIt)
|
|
||||||
{
|
|
||||||
std::cout << " 1 " << (std::bitset<8>) (*txIt) << " 0 ";
|
|
||||||
}
|
|
||||||
std::cout << "]" << std::endl;
|
|
||||||
|
|
||||||
|
int loopCnt = 0;
|
||||||
std::cout << "Type 'c' to continue, 'q' or 'x' to quit: ";
|
std::cout << "Type 'c' to continue, 'q' or 'x' to quit: ";
|
||||||
while (_running)
|
while (_running)
|
||||||
{
|
{
|
||||||
@ -182,38 +217,28 @@ int main()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = write(uart0_filestream, &tx_buffer[0], (p_tx_buffer - &tx_buffer[0])); //Filestream, bytes to write, number of bytes to write
|
set_realtime_priority();
|
||||||
if (count < 0)
|
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 -----
|
usleep(100000);
|
||||||
close(uart0_filestream);
|
++loopCnt;
|
||||||
return -1;
|
|
||||||
}
|
if (loopCnt%3 == 2)
|
||||||
std::cout << "Writing " << count << " bytes to uart" << std::endl;
|
signalData = std::vector<ColorSignal>(10, GREEN_Signal);
|
||||||
|
else if(loopCnt%3 == 1)
|
||||||
|
signalData = std::vector<ColorSignal>(10, BLUE_Signal);
|
||||||
|
else if(loopCnt%3 == 0)
|
||||||
|
signalData = std::vector<ColorSignal>(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<ColorSignal>(50, BLACK_Signal);
|
||||||
|
write(uart0_filestream, signalData.data(), signalData.size()*sizeof(ColorSignal));
|
||||||
//----- CLOSE THE UART -----
|
//----- CLOSE THE UART -----
|
||||||
close(uart0_filestream);
|
close(uart0_filestream);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user