util.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2021 Eurotec, Netherlands
3  * All rights reserved.
4  *
5  * Author: Jad Haj Mustafa
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * 3. Neither the name of the copyright holder nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <algorithm>
36 #include <libusb-1.0/libusb.h>
37 #include <list>
38 #include <math.h>
39 #include <stdexcept>
40 
41 #include "./util.h"
42 
43 namespace fadecandy_driver
44 {
45 constexpr int LEDS_PER_PACKET = 21;
46 constexpr int LOOKUP_VALUES_PER_PACKET = 31;
47 constexpr int LOOKUP_VALUES_PER_CHANNEL = 257;
48 constexpr int USB_PACKET_SIZE = 64;
49 constexpr int PACKET_TYPE_VIDEO = 0x00;
50 constexpr int PACKET_TYPE_LUT = 0x40;
51 constexpr int FINAL_PACKET_BIT = 0x20;
52 constexpr int LEDS_PER_STRIP = 64;
53 constexpr int NUM_STRIPS = 8;
54 
55 Color::Color(int r, int g, int b) : r_(r), g_(g), b_(b)
56 {
57 }
58 
59 std::vector<unsigned char> intToCharArray(int in, const size_t bytes_per_int)
60 {
61  if (in > pow(2, bytes_per_int * 8))
62  {
63  throw std::overflow_error("Overflow error while converting integer " + std::to_string(in) + " to char array of " +
64  std::to_string(bytes_per_int) + " bytes");
65  }
66  unsigned char buffer[bytes_per_int];
67  std::vector<unsigned char> char_array;
68  for (size_t i = 0; i < bytes_per_int; i++)
69  {
70  size_t shift = 8 * (bytes_per_int - 1 - i);
71  buffer[i] = (in >> shift) & 0xff;
72  char_array.push_back(buffer[i]);
73  }
74  std::reverse(char_array.begin(), char_array.end());
75  return char_array;
76 }
77 
78 std::vector<std::vector<unsigned char>> makeVideoUsbPackets(const std::vector<std::vector<Color>>& led_array_colors)
79 {
80  int led_index = 0;
81  std::vector<Color> all_led_colors(LEDS_PER_STRIP * NUM_STRIPS, { 0, 0, 0 });
82  for (size_t i = 0; i < led_array_colors.size(); i++)
83  {
84  for (size_t j = 0; j < led_array_colors[i].size(); j++)
85  {
86  led_index = (i * LEDS_PER_STRIP) + j;
87  all_led_colors[led_index] = led_array_colors[i][j];
88  }
89  }
90  std::vector<std::vector<unsigned char>> packets;
91  std::vector<Color> packet_leds;
92  int control;
93 
94  while (all_led_colors.size() > 0)
95  {
96  std::vector<int> color_bytes;
97  std::vector<unsigned char> packet;
98 
99  if (all_led_colors.size() < LEDS_PER_PACKET)
100  {
101  packet_leds.assign(all_led_colors.begin(), all_led_colors.end());
102  all_led_colors.erase(all_led_colors.begin(), all_led_colors.end());
103  }
104  else
105  {
106  packet_leds.assign(all_led_colors.begin(), all_led_colors.begin() + LEDS_PER_PACKET);
107  all_led_colors.erase(all_led_colors.begin(), all_led_colors.begin() + LEDS_PER_PACKET);
108  }
109 
110  control = packets.size() | PACKET_TYPE_VIDEO;
111  if (all_led_colors.size() == 0)
112  {
113  control |= FINAL_PACKET_BIT;
114  }
115 
116  for (size_t i = 0; i < packet_leds.size(); i++)
117  {
118  color_bytes.push_back(packet_leds[i].r_);
119  color_bytes.push_back(packet_leds[i].g_);
120  color_bytes.push_back(packet_leds[i].b_);
121  }
122  // construnt USB packet and leave the first byte for the control byte
123  if ((USB_PACKET_SIZE - 1) - color_bytes.size() > 0)
124  {
125  int j = (USB_PACKET_SIZE - 1) - color_bytes.size();
126  for (int i = 0; i < j; i++)
127  {
128  color_bytes.push_back(0);
129  }
130  }
131 
132  for (size_t i = 0; i < color_bytes.size(); i++)
133  {
134  int bytes_per_int = 1;
135  std::vector<unsigned char> bufferv;
136  bufferv = intToCharArray(color_bytes[i], bytes_per_int);
137  packet.insert(packet.end(), bufferv.begin(), bufferv.end());
138  }
139 
140  // add control byte
141  packet.insert(packet.begin(), static_cast<unsigned char>(control));
142 
143  if (packet.size() != USB_PACKET_SIZE)
144  {
145  throw std::runtime_error("Packet size does not match the allowed USB packet size");
146  }
147  packets.push_back(packet);
148  }
149  return packets;
150 }
151 
152 std::vector<std::vector<unsigned char>> makeLookupTablePackets(const std::vector<int>& red_lookup_values,
153  const std::vector<int>& green_lookup_values,
154  const std::vector<int>& blue_lookup_values)
155 {
156  if (red_lookup_values.size() != LOOKUP_VALUES_PER_CHANNEL ||
157  green_lookup_values.size() != LOOKUP_VALUES_PER_CHANNEL || blue_lookup_values.size() != LOOKUP_VALUES_PER_CHANNEL)
158  {
159  throw std::runtime_error("Lookup values per channel is not correct");
160  }
161  std::vector<std::vector<unsigned char>> packets;
162  std::vector<int> remaining_lookup_values;
163  std::vector<int> packet_lookup_values;
164  int control;
165 
166  remaining_lookup_values.insert(remaining_lookup_values.begin(), red_lookup_values.begin(), red_lookup_values.end());
167  remaining_lookup_values.insert(remaining_lookup_values.end(), green_lookup_values.begin(), green_lookup_values.end());
168  remaining_lookup_values.insert(remaining_lookup_values.end(), blue_lookup_values.begin(), blue_lookup_values.end());
169 
170  while (remaining_lookup_values.size() > 0)
171  {
172  std::vector<unsigned char> packet;
173 
174  if (remaining_lookup_values.size() < LOOKUP_VALUES_PER_PACKET)
175  {
176  packet_lookup_values.assign(remaining_lookup_values.begin(), remaining_lookup_values.end());
177  remaining_lookup_values.erase(remaining_lookup_values.begin(), remaining_lookup_values.end());
178  }
179  else
180  {
181  packet_lookup_values.assign(remaining_lookup_values.begin(),
182  remaining_lookup_values.begin() + LOOKUP_VALUES_PER_PACKET);
183  remaining_lookup_values.erase(remaining_lookup_values.begin(),
184  remaining_lookup_values.begin() + LOOKUP_VALUES_PER_PACKET);
185  }
186  control = packets.size() | PACKET_TYPE_LUT;
187  if (remaining_lookup_values.size() == 0)
188  {
189  control |= FINAL_PACKET_BIT;
190  }
191 
192  if (LOOKUP_VALUES_PER_PACKET - packet_lookup_values.size() > 0)
193  {
194  int j = LOOKUP_VALUES_PER_PACKET - packet_lookup_values.size();
195  for (int i = 0; i < j; i++)
196  {
197  packet_lookup_values.push_back(0);
198  }
199  }
200 
201  for (size_t i = 0; i < packet_lookup_values.size(); i++)
202  {
203  int bytes_per_int = 2;
204  std::vector<unsigned char> bufferv;
205  bufferv = intToCharArray(packet_lookup_values[i], bytes_per_int);
206  packet.insert(packet.end(), bufferv.begin(), bufferv.end());
207  }
208  // add control byte
209  packet.insert(packet.begin(), static_cast<unsigned char>(0));
210  packet.insert(packet.begin(), static_cast<unsigned char>(control));
211 
212  if (packet.size() != USB_PACKET_SIZE)
213  {
214  throw std::runtime_error("Packet size does not match the allowed USB packet size");
215  }
216  packets.push_back(packet);
217  }
218  return packets;
219 }
220 
221 std::vector<int> makeDefaultLookupTable()
222 {
223  //
224  // color correction curve borrowed from the USB example in the main fadecandy repo:
225  //
226  // https://github.com/scanlime/fadecandy/blob/master/examples/python/usb-lowlevel.py
227  //
228  std::vector<int> lookup_values;
229  for (int row = 0; row < 257; row++)
230  {
231  lookup_values.push_back(std::min(0xFFFF, int(pow(row / 256.0, 2.2) * 0x10000)));
232  }
233  return lookup_values;
234 }
235 } // namespace fadecandy_driver
fadecandy_driver::USB_PACKET_SIZE
constexpr int USB_PACKET_SIZE
Definition: fadecandy_driver.cpp:41
fadecandy_driver::intToCharArray
std::vector< unsigned char > intToCharArray(int in, const size_t bytes_per_int)
Definition: util.cpp:59
fadecandy_driver::NUM_STRIPS
constexpr int NUM_STRIPS
Definition: util.cpp:53
fadecandy_driver::PACKET_TYPE_LUT
constexpr int PACKET_TYPE_LUT
Definition: util.cpp:50
fadecandy_driver::makeVideoUsbPackets
std::vector< std::vector< unsigned char > > makeVideoUsbPackets(const std::vector< std::vector< Color >> &led_array_colors)
makeVideoUsbPackets Construct the USB packets to set all LED strips to the given colors....
Definition: util.cpp:78
fadecandy_driver::LEDS_PER_STRIP
constexpr int LEDS_PER_STRIP
Definition: util.cpp:52
fadecandy_driver::FINAL_PACKET_BIT
constexpr int FINAL_PACKET_BIT
Definition: util.cpp:51
fadecandy_driver::LEDS_PER_PACKET
constexpr int LEDS_PER_PACKET
Definition: util.cpp:45
fadecandy_driver::LOOKUP_VALUES_PER_CHANNEL
constexpr int LOOKUP_VALUES_PER_CHANNEL
Definition: util.cpp:47
fadecandy_driver::PACKET_TYPE_VIDEO
constexpr int PACKET_TYPE_VIDEO
Definition: util.cpp:49
fadecandy_driver::makeDefaultLookupTable
std::vector< int > makeDefaultLookupTable()
makeLookupTablePackets Return lookup tables as 3 lists of lookup values - one for the red channel,...
Definition: util.cpp:221
fadecandy_driver::LOOKUP_VALUES_PER_PACKET
constexpr int LOOKUP_VALUES_PER_PACKET
Definition: util.cpp:46
fadecandy_driver::Color::Color
Color(int r, int g, int b)
Definition: util.cpp:55
fadecandy_driver
Definition: fadecandy_driver.cpp:39
util.h
fadecandy_driver::makeLookupTablePackets
std::vector< std::vector< unsigned char > > makeLookupTablePackets(const std::vector< int > &red_lookup_values, const std::vector< int > &green_lookup_values, const std::vector< int > &blue_lookup_values)
makeLookupTablePackets Create USB packets for a simple color lookup table. The entire red lookup tabl...
Definition: util.cpp:152


fadecandy_driver
Author(s):
autogenerated on Wed Mar 2 2022 00:19:01