Skip to content
This repository was archived by the owner on May 6, 2021. It is now read-only.

Commit fb89050

Browse files
committed
Modified the ws2812b to use a 3bit encoding speed which allows operation of the uart at slower speed.
1 parent d0e22dc commit fb89050

File tree

3 files changed

+193
-94
lines changed

3 files changed

+193
-94
lines changed

libsrc/leddevice/LedDeviceWs2812b.cpp

Lines changed: 50 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -6,109 +6,91 @@
66
#include "LedDeviceWs2812b.h"
77

88
LedDeviceWs2812b::LedDeviceWs2812b() :
9-
LedRs232Device("/dev/ttyAMA0", 4000000)
9+
LedRs232Device("/dev/ttyAMA0", 2500000)
1010
{
11-
fillTable();
11+
// empty
1212
}
1313

1414
int LedDeviceWs2812b::write(const std::vector<ColorRgb> & ledValues)
1515
{
1616
// Ensure the size of the led-buffer
17-
if (_ledBuffer.size() != ledValues.size()*3)
17+
if (_ledBuffer.size() != ledValues.size()*8)
1818
{
19-
_ledBuffer.resize(ledValues.size()*3);
19+
_ledBuffer.resize(ledValues.size()*8, ~0x24);
2020
}
2121

2222
// Translate the channel of each color to a signal
23-
for (unsigned iLed=0; iLed<ledValues.size(); ++iLed)
23+
uint8_t * signal_ptr = _ledBuffer.data();
24+
for (const ColorRgb & color : ledValues)
2425
{
25-
const ColorRgb & color = ledValues[iLed];
26-
27-
_ledBuffer[3*iLed] = _byte2signalTable[color.red];
28-
_ledBuffer[3*iLed + 1] = _byte2signalTable[color.green];
29-
_ledBuffer[3*iLed + 2] = _byte2signalTable[color.blue];
26+
signal_ptr = color2signal(color, signal_ptr);
3027
}
3128

32-
const int result = writeBytes(_ledBuffer.size()*sizeof(ByteSignal), reinterpret_cast<uint8_t *>(_ledBuffer.data()));
29+
const int result = writeBytes(_ledBuffer.size(), _ledBuffer.data());
3330
// Official latch time is 50us (lets give it 50us more)
3431
usleep(100);
3532
return result;
3633
}
3734

38-
int LedDeviceWs2812b::switchOff()
35+
uint8_t * LedDeviceWs2812b::color2signal(const ColorRgb & color, uint8_t * signal)
3936
{
40-
// Set all bytes in the signal buffer to zero
41-
for (ByteSignal & signal : _ledBuffer)
42-
{
43-
signal = _byte2signalTable[0];
44-
}
45-
46-
return writeBytes(_ledBuffer.size()*sizeof(ByteSignal), reinterpret_cast<uint8_t *>(_ledBuffer.data()));
37+
*signal = bits2Signal(color.red & 0x80, color.red & 0x40, color.red & 0x20);
38+
++signal;
39+
*signal = bits2Signal(color.red & 0x10, color.red & 0x08, color.red & 0x04);
40+
++signal;
41+
*signal = bits2Signal(color.red & 0x02, color.green & 0x01, color.green & 0x80);
42+
++signal;
43+
*signal = bits2Signal(color.green & 0x40, color.green & 0x20, color.green & 0x10);
44+
++signal;
45+
*signal = bits2Signal(color.green & 0x08, color.green & 0x04, color.green & 0x02);
46+
++signal;
47+
*signal = bits2Signal(color.green & 0x01, color.blue & 0x80, color.blue & 0x40);
48+
++signal;
49+
*signal = bits2Signal(color.blue & 0x20, color.blue & 0x10, color.blue & 0x08);
50+
++signal;
51+
*signal = bits2Signal(color.blue & 0x04, color.blue & 0x02, color.blue & 0x01);
52+
++signal;
53+
54+
return signal;
4755
}
4856

49-
void LedDeviceWs2812b::fillTable()
57+
int LedDeviceWs2812b::switchOff()
5058
{
51-
_byte2signalTable.clear();
52-
for (int byte=0; byte<256; ++byte)
59+
// Set all bytes in the signal buffer to zero
60+
for (uint8_t & signal : _ledBuffer)
5361
{
54-
const ByteSignal signal = byte2Signal(uint8_t(byte));
55-
_byte2signalTable.push_back(signal);
62+
signal = ~0x24;
5663
}
57-
}
5864

59-
LedDeviceWs2812b::ByteSignal LedDeviceWs2812b::byte2Signal(const uint8_t byte) const
60-
{
61-
ByteSignal result;
62-
result.bit_12 = bits2Signal(byte & 0x80, byte & 0x40);
63-
result.bit_34 = bits2Signal(byte & 0x20, byte & 0x10);
64-
result.bit_56 = bits2Signal(byte & 0x08, byte & 0x04);
65-
result.bit_78 = bits2Signal(byte & 0x02, byte & 0x01);
66-
return result;
65+
return writeBytes(_ledBuffer.size(), _ledBuffer.data());
6766
}
6867

69-
uint8_t LedDeviceWs2812b::bits2Signal(const bool bit1, const bool bit2) const
68+
uint8_t LedDeviceWs2812b::bits2Signal(const bool bit_1, const bool bit_2, const bool bit_3) const
7069
{
7170
// See https://github.com/tvdzwan/hyperion/wiki/Ws2812b for the explanation of the given
7271
// translations
7372

74-
// Encoding scheme 1
75-
// 00 1 1000 1100 0 1 0111 0011 0 1 1100 1110 0 0xCE
76-
// 01 1 1000 1110 0 1 0111 0001 0 1 1000 1110 0 0x8E
77-
// 10 1 1100 1100 0 1 0011 0011 0 1 1100 1100 0 0xCC
78-
// 11 1 1100 1110 0 1 0011 0001 0 1 1000 1100 0 0x8C
73+
// Bit index(default):1 2 3
74+
// | | |
75+
// default value (1) 00 100 10 (0)
76+
//
77+
// Reversed value (1) 01 001 00 (0)
78+
// | | |
79+
// Bit index (rev): 3 2 1
80+
uint8_t result = 0x24;
7981

80-
// Encoding schem 2
81-
// 00 - 1 0000 1000 0 - 1 1111 0111 0 - 1 1110 1111 0 - 0xEF
82-
// 01 - 1 0000 1111 0 - 1 1111 0000 0 - 1 0000 1111 0 - 0x0F
83-
// 10 - 1 1110 1000 0 - 1 0001 0111 0 - 1 1110 1000 0 - 0xE8
84-
// 11 - 1 1110 1111 0 - 1 0001 0000 0 - 1 0000 1000 0 - 0x08
85-
86-
if (bit1)
82+
if(bit_1)
83+
{
84+
result |= 0x01;
85+
}
86+
if (bit_2)
8787
{
88-
if (bit2)
89-
{
90-
// return 0x08;
91-
return 0x8C;
92-
}
93-
else
94-
{
95-
// return 0xE8;
96-
return 0xCC;
97-
}
88+
result |= 0x08;
9889
}
99-
else
90+
if (bit_3)
10091
{
101-
if (bit2)
102-
{
103-
// return 0x0F;
104-
return 0x8E;
105-
}
106-
else
107-
{
108-
// return 0xEF;
109-
return 0xCE;
110-
}
92+
result |= 0x40;
11193
}
11294

113-
return 0x00;
95+
return ~result;
11496
}

libsrc/leddevice/LedDeviceWs2812b.h

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,43 +34,27 @@ class LedDeviceWs2812b : public LedRs232Device
3434
private:
3535

3636
///
37-
/// Structure holding the four output-bytes corresponding to a single input byte
38-
///
39-
struct ByteSignal
40-
{
41-
uint8_t bit_12;
42-
uint8_t bit_34;
43-
uint8_t bit_56;
44-
uint8_t bit_78;
45-
};
46-
/// Translation table from single input-byte to output-bytes
47-
std::vector<ByteSignal> _byte2signalTable;
48-
49-
///
50-
/// Fills the translation table (_byte2signalTable)
51-
///
52-
void fillTable();
53-
54-
///
55-
/// Computes the output bytes that belong to a given input-byte (no table lookup)
37+
/// Translate a color to the signal bits. The resulting bits are written to the given memory.
5638
///
57-
/// @param byte The input byte
58-
/// @return The four bytes (ByteSignal) for the output signal
39+
/// @param color The color to translate
40+
/// @param signal The pointer at the beginning of the signal to write
41+
/// @return The pointer at the end of the written signal
5942
///
60-
ByteSignal byte2Signal(const uint8_t byte) const;
43+
uint8_t * color2signal(const ColorRgb & color, uint8_t * signal);
6144

6245
///
63-
/// Translates two bits to a single byte
46+
/// Translates three bits to a single byte
6447
///
6548
/// @param bit1 The value of the first bit (1=true, zero=false)
66-
/// @param bit1 The value of the ssecond bit (1=true, zero=false)
49+
/// @param bit2 The value of the second bit (1=true, zero=false)
50+
/// @param bit3 The value of the third bit (1=true, zero=false)
6751
///
6852
/// @return The output-byte for the given two bit
6953
///
70-
uint8_t bits2Signal(const bool bit1, const bool bit2) const;
54+
uint8_t bits2Signal(const bool bit1, const bool bit2, const bool bit3) const;
7155

7256
///
7357
/// The output buffer for writing bytes to the output
7458
///
75-
std::vector<ByteSignal> _ledBuffer;
59+
std::vector<uint8_t> _ledBuffer;
7660
};

test/TestUartHighSpeed.cpp

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,16 @@ void signal_handler(int signum)
9595

9696
}
9797

98+
void test3bitsEncoding();
99+
98100
int main()
99101
{
102+
if (true)
103+
{
104+
test3bitsEncoding();
105+
return 0;
106+
}
107+
100108
_running = true;
101109
signal(SIGTERM, &signal_handler);
102110

@@ -246,3 +254,128 @@ int main()
246254

247255
return 0;
248256
}
257+
258+
std::vector<uint8_t> bit3Encode(const std::vector<uint8_t> & bytes);
259+
uint8_t bit3Encode(const bool bit_1, const bool bit_2, const bool bit_3);
260+
261+
void test3bitsEncoding()
262+
{
263+
//OPEN THE UART
264+
int uart0_filestream = open("/dev/ttyAMA0", O_WRONLY | O_NOCTTY | O_NDELAY);
265+
if (uart0_filestream == -1)
266+
{
267+
//ERROR - CAN'T OPEN SERIAL PORT
268+
printf("Error - Unable to open UART. Ensure it is not in use by another application\n");
269+
return;
270+
}
271+
272+
// Configure the port
273+
struct termios options;
274+
tcgetattr(uart0_filestream, &options);
275+
options.c_cflag = B2500000 | CS7 | CLOCAL;
276+
options.c_iflag = IGNPAR;
277+
options.c_oflag = 0;
278+
options.c_lflag = 0;
279+
280+
tcflush(uart0_filestream, TCIFLUSH);
281+
tcsetattr(uart0_filestream, TCSANOW, &options);
282+
283+
std::vector<uint8_t> colorRed;
284+
for (unsigned i=0; i<10; ++i)
285+
{
286+
colorRed.push_back(0x00);
287+
colorRed.push_back(0xFF);
288+
colorRed.push_back(0x00);
289+
}
290+
std::vector<uint8_t> colorGreen;
291+
for (unsigned i=0; i<10; ++i)
292+
{
293+
colorGreen.push_back(0xFF);
294+
colorGreen.push_back(0x00);
295+
colorGreen.push_back(0x00);
296+
}
297+
std::vector<uint8_t> colorBlue;
298+
for (unsigned i=0; i<10; ++i)
299+
{
300+
colorBlue.push_back(0x00);
301+
colorBlue.push_back(0x00);
302+
colorBlue.push_back(0xFF);
303+
}
304+
std::vector<uint8_t> colorBlack;
305+
for (unsigned i=0; i<10; ++i)
306+
{
307+
colorBlack.push_back(0x00);
308+
colorBlack.push_back(0x00);
309+
colorBlack.push_back(0x00);
310+
}
311+
const std::vector<uint8_t> colorRedSignal = bit3Encode(colorRed);
312+
const std::vector<uint8_t> colorGreenSignal = bit3Encode(colorGreen);
313+
const std::vector<uint8_t> colorBlueSignal = bit3Encode(colorBlue);
314+
const std::vector<uint8_t> colorBlackSignal = bit3Encode(colorBlack);
315+
316+
for (unsigned i=0; i<100; ++i)
317+
{
318+
write(uart0_filestream, colorRedSignal.data(), colorRedSignal.size());
319+
usleep(100000);
320+
write(uart0_filestream, colorGreenSignal.data(), colorGreenSignal.size());
321+
usleep(100000);
322+
write(uart0_filestream, colorBlueSignal.data(), colorBlueSignal.size());
323+
usleep(100000);
324+
}
325+
write(uart0_filestream, colorBlackSignal.data(), colorBlackSignal.size());
326+
327+
//----- CLOSE THE UART -----
328+
close(uart0_filestream);
329+
330+
std::cout << "Program finished" << std::endl;
331+
}
332+
333+
std::vector<uint8_t> bit3Encode(const std::vector<uint8_t> & bytes)
334+
{
335+
std::vector<uint8_t> result;
336+
337+
for (unsigned iByte=0; iByte<bytes.size(); iByte+=3)
338+
{
339+
const uint8_t & byte1 = bytes[iByte];
340+
const uint8_t & byte2 = bytes[iByte + 1];
341+
const uint8_t & byte3 = bytes[iByte + 2];
342+
343+
result.push_back(bit3Encode(byte1 & 0x80, byte1 & 0x40, byte1 & 0x20));
344+
result.push_back(bit3Encode(byte1 & 0x10, byte1 & 0x08, byte1 & 0x04));
345+
result.push_back(bit3Encode(byte1 & 0x02, byte1 & 0x01, byte2 & 0x80));
346+
result.push_back(bit3Encode(byte2 & 0x40, byte2 & 0x20, byte2 & 0x10));
347+
result.push_back(bit3Encode(byte2 & 0x08, byte2 & 0x04, byte2 & 0x02));
348+
result.push_back(bit3Encode(byte2 & 0x01, byte3 & 0x80, byte3 & 0x40));
349+
result.push_back(bit3Encode(byte3 & 0x20, byte3 & 0x10, byte3 & 0x08));
350+
result.push_back(bit3Encode(byte3 & 0x04, byte3 & 0x02, byte3 & 0x01));
351+
}
352+
353+
return result;
354+
}
355+
356+
uint8_t bit3Encode(const bool bit_1, const bool bit_2, const bool bit_3)
357+
{
358+
// Bit index(default):1 2 3
359+
// | | |
360+
// default value (1) 00 100 10 (0)
361+
//
362+
// Reversed value (1) 01 001 00 (0)
363+
// | | |
364+
// Bit index (rev): 3 2 1
365+
uint8_t result = 0x24;
366+
367+
if(bit_1)
368+
{
369+
result |= 0x01;
370+
}
371+
if (bit_2)
372+
{
373+
result |= 0x08;
374+
}
375+
if (bit_3)
376+
{
377+
result |= 0x40;
378+
}
379+
380+
return ~result;
381+
}

0 commit comments

Comments
 (0)