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

Commit cd81030

Browse files
committed
Add hyperion-usbasp led devices
Remove all WS281x direct UART code (does not work reliable)
1 parent 1b98924 commit cd81030

14 files changed

+308
-1638
lines changed

libsrc/leddevice/CMakeLists.txt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ SET(Leddevice_HEADERS
2828
${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.h
2929
${CURRENT_SOURCE_DIR}/LedDeviceSedu.h
3030
${CURRENT_SOURCE_DIR}/LedDeviceTest.h
31-
${CURRENT_SOURCE_DIR}/LedDeviceWs2812b.h
32-
${CURRENT_SOURCE_DIR}/LedDeviceWs2811.h
31+
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.h
3332
)
3433

3534
SET(Leddevice_SOURCES
@@ -44,8 +43,7 @@ SET(Leddevice_SOURCES
4443
${CURRENT_SOURCE_DIR}/LedDevicePiBlaster.cpp
4544
${CURRENT_SOURCE_DIR}/LedDeviceSedu.cpp
4645
${CURRENT_SOURCE_DIR}/LedDeviceTest.cpp
47-
${CURRENT_SOURCE_DIR}/LedDeviceWs2811.cpp
48-
${CURRENT_SOURCE_DIR}/LedDeviceWs2812b.cpp
46+
${CURRENT_SOURCE_DIR}/LedDeviceHyperionUsbasp.cpp
4947
)
5048

5149
if(ENABLE_SPIDEV)

libsrc/leddevice/LedDeviceFactory.cpp

Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
#include "LedDevicePiBlaster.h"
2424
#include "LedDeviceSedu.h"
2525
#include "LedDeviceTest.h"
26-
#include "LedDeviceWs2811.h"
27-
#include "LedDeviceWs2812b.h"
26+
#include "LedDeviceHyperionUsbasp.h"
2827

2928
LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
3029
{
@@ -87,23 +86,6 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
8786
device = deviceWs2801;
8887
}
8988
#endif
90-
// else if (type == "ws2811")
91-
// {
92-
// const std::string output = deviceConfig["output"].asString();
93-
// const std::string outputSpeed = deviceConfig["output"].asString();
94-
// const std::string timingOption = deviceConfig["timingOption"].asString();
95-
96-
// ws2811::SpeedMode speedMode = (outputSpeed == "high")? ws2811::highspeed : ws2811::lowspeed;
97-
// if (outputSpeed != "high" && outputSpeed != "low")
98-
// {
99-
// std::cerr << "Incorrect speed-mode selected for WS2811: " << outputSpeed << " != {'high', 'low'}" << std::endl;
100-
// }
101-
102-
// LedDeviceWs2811 * deviceWs2811 = new LedDeviceWs2811(output, ws2811::fromString(timingOption, ws2811::option_2855), speedMode);
103-
// deviceWs2811->open();
104-
105-
// device = deviceWs2811;
106-
// }
10789
else if (type == "lightpack")
10890
{
10991
const std::string output = deviceConfig.get("output", "").asString();
@@ -147,18 +129,23 @@ LedDevice * LedDeviceFactory::construct(const Json::Value & deviceConfig)
147129

148130
device = deviceSedu;
149131
}
132+
else if (type == "hyperion-usbasp-ws2801")
133+
{
134+
LedDeviceHyperionUsbasp * deviceHyperionUsbasp = new LedDeviceHyperionUsbasp(LedDeviceHyperionUsbasp::CMD_WRITE_WS2801);
135+
deviceHyperionUsbasp->open();
136+
device = deviceHyperionUsbasp;
137+
}
138+
else if (type == "hyperion-usbasp-ws2812")
139+
{
140+
LedDeviceHyperionUsbasp * deviceHyperionUsbasp = new LedDeviceHyperionUsbasp(LedDeviceHyperionUsbasp::CMD_WRITE_WS2812);
141+
deviceHyperionUsbasp->open();
142+
device = deviceHyperionUsbasp;
143+
}
150144
else if (type == "test")
151145
{
152146
const std::string output = deviceConfig["output"].asString();
153147
device = new LedDeviceTest(output);
154148
}
155-
else if (type == "ws2812b")
156-
{
157-
LedDeviceWs2812b * deviceWs2812b = new LedDeviceWs2812b();
158-
deviceWs2812b->open();
159-
160-
device = deviceWs2812b;
161-
}
162149
else
163150
{
164151
std::cout << "Unable to create device " << type << std::endl;
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
// stl includes
2+
#include <exception>
3+
#include <cstring>
4+
5+
// Local Hyperion includes
6+
#include "LedDeviceHyperionUsbasp.h"
7+
8+
// Static constants which define the Hyperion Usbasp device
9+
uint16_t LedDeviceHyperionUsbasp::_usbVendorId = 0x16c0;
10+
uint16_t LedDeviceHyperionUsbasp::_usbProductId = 0x05dc;
11+
std::string LedDeviceHyperionUsbasp::_usbProductDescription = "Hyperion led controller";
12+
13+
14+
LedDeviceHyperionUsbasp::LedDeviceHyperionUsbasp(uint8_t writeLedsCommand) :
15+
LedDevice(),
16+
_writeLedsCommand(writeLedsCommand),
17+
_libusbContext(nullptr),
18+
_deviceHandle(nullptr),
19+
_ledCount(256)
20+
{
21+
}
22+
23+
LedDeviceHyperionUsbasp::~LedDeviceHyperionUsbasp()
24+
{
25+
if (_deviceHandle != nullptr)
26+
{
27+
libusb_release_interface(_deviceHandle, 0);
28+
libusb_attach_kernel_driver(_deviceHandle, 0);
29+
libusb_close(_deviceHandle);
30+
31+
_deviceHandle = nullptr;
32+
}
33+
34+
if (_libusbContext != nullptr)
35+
{
36+
libusb_exit(_libusbContext);
37+
_libusbContext = nullptr;
38+
}
39+
}
40+
41+
int LedDeviceHyperionUsbasp::open()
42+
{
43+
int error;
44+
45+
// initialize the usb context
46+
if ((error = libusb_init(&_libusbContext)) != LIBUSB_SUCCESS)
47+
{
48+
std::cerr << "Error while initializing USB context(" << error << "): " << libusb_error_name(error) << std::endl;
49+
_libusbContext = nullptr;
50+
return -1;
51+
}
52+
//libusb_set_debug(_libusbContext, 3);
53+
std::cout << "USB context initialized" << std::endl;
54+
55+
// retrieve the list of usb devices
56+
libusb_device ** deviceList;
57+
ssize_t deviceCount = libusb_get_device_list(_libusbContext, &deviceList);
58+
59+
// iterate the list of devices
60+
for (ssize_t i = 0 ; i < deviceCount; ++i)
61+
{
62+
// try to open and initialize the device
63+
error = testAndOpen(deviceList[i]);
64+
65+
if (error == 0)
66+
{
67+
// a device was sucessfully opened. break from list
68+
break;
69+
}
70+
}
71+
72+
// free the device list
73+
libusb_free_device_list(deviceList, 1);
74+
75+
if (_deviceHandle == nullptr)
76+
{
77+
std::cerr << "No " << _usbProductDescription << " has been found" << std::endl;
78+
}
79+
80+
return _deviceHandle == nullptr ? -1 : 0;
81+
}
82+
83+
int LedDeviceHyperionUsbasp::testAndOpen(libusb_device * device)
84+
{
85+
libusb_device_descriptor deviceDescriptor;
86+
int error = libusb_get_device_descriptor(device, &deviceDescriptor);
87+
if (error != LIBUSB_SUCCESS)
88+
{
89+
std::cerr << "Error while retrieving device descriptor(" << error << "): " << libusb_error_name(error) << std::endl;
90+
return -1;
91+
}
92+
93+
if (deviceDescriptor.idVendor == _usbVendorId &&
94+
deviceDescriptor.idProduct == _usbProductId &&
95+
deviceDescriptor.iProduct != 0 &&
96+
getString(device, deviceDescriptor.iProduct) == _usbProductDescription)
97+
{
98+
// get the hardware address
99+
int busNumber = libusb_get_bus_number(device);
100+
int addressNumber = libusb_get_device_address(device);
101+
102+
std::cout << _usbProductDescription << " found: bus=" << busNumber << " address=" << addressNumber << std::endl;
103+
104+
try
105+
{
106+
_deviceHandle = openDevice(device);
107+
std::cout << _usbProductDescription << " successfully opened" << std::endl;
108+
return 0;
109+
}
110+
catch(int e)
111+
{
112+
_deviceHandle = nullptr;
113+
std::cerr << "Unable to open " << _usbProductDescription << ". Searching for other device(" << e << "): " << libusb_error_name(e) << std::endl;
114+
}
115+
}
116+
117+
return -1;
118+
}
119+
120+
int LedDeviceHyperionUsbasp::write(const std::vector<ColorRgb> &ledValues)
121+
{
122+
_ledCount = ledValues.size();
123+
124+
int nbytes = libusb_control_transfer(
125+
_deviceHandle, // device handle
126+
LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT, // request type
127+
_writeLedsCommand, // request
128+
0, // value
129+
0, // index
130+
(uint8_t *) ledValues.data(), // data
131+
(3*_ledCount) & 0xffff, // length
132+
5000); // timeout
133+
134+
// Disabling interupts for a little while on the device results in a PIPE error. All seems to keep functioning though...
135+
if(nbytes < 0 && nbytes != LIBUSB_ERROR_PIPE)
136+
{
137+
std::cerr << "Error while writing data to " << _usbProductDescription << " (" << libusb_error_name(nbytes) << ")" << std::endl;
138+
return -1;
139+
}
140+
141+
return 0;
142+
}
143+
144+
int LedDeviceHyperionUsbasp::switchOff()
145+
{
146+
std::vector<ColorRgb> ledValues(_ledCount, ColorRgb::BLACK);
147+
return write(ledValues);
148+
}
149+
150+
libusb_device_handle * LedDeviceHyperionUsbasp::openDevice(libusb_device *device)
151+
{
152+
libusb_device_handle * handle = nullptr;
153+
154+
int error = libusb_open(device, &handle);
155+
if (error != LIBUSB_SUCCESS)
156+
{
157+
std::cerr << "unable to open device(" << error << "): " << libusb_error_name(error) << std::endl;
158+
throw error;
159+
}
160+
161+
// detach kernel driver if it is active
162+
if (libusb_kernel_driver_active(handle, 0) == 1)
163+
{
164+
error = libusb_detach_kernel_driver(handle, 0);
165+
if (error != LIBUSB_SUCCESS)
166+
{
167+
std::cerr << "unable to detach kernel driver(" << error << "): " << libusb_error_name(error) << std::endl;
168+
libusb_close(handle);
169+
throw error;
170+
}
171+
}
172+
173+
error = libusb_claim_interface(handle, 0);
174+
if (error != LIBUSB_SUCCESS)
175+
{
176+
std::cerr << "unable to claim interface(" << error << "): " << libusb_error_name(error) << std::endl;
177+
libusb_attach_kernel_driver(handle, 0);
178+
libusb_close(handle);
179+
throw error;
180+
}
181+
182+
return handle;
183+
}
184+
185+
std::string LedDeviceHyperionUsbasp::getString(libusb_device * device, int stringDescriptorIndex)
186+
{
187+
libusb_device_handle * handle = nullptr;
188+
189+
int error = libusb_open(device, &handle);
190+
if (error != LIBUSB_SUCCESS)
191+
{
192+
throw error;
193+
}
194+
195+
char buffer[256];
196+
error = libusb_get_string_descriptor_ascii(handle, stringDescriptorIndex, reinterpret_cast<unsigned char *>(buffer), sizeof(buffer));
197+
if (error <= 0)
198+
{
199+
libusb_close(handle);
200+
throw error;
201+
}
202+
203+
libusb_close(handle);
204+
return std::string(buffer, error);
205+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#pragma once
2+
3+
// stl includes
4+
#include <vector>
5+
#include <cstdint>
6+
#include <string>
7+
8+
// libusb include
9+
#include <libusb.h>
10+
11+
// Hyperion includes
12+
#include <leddevice/LedDevice.h>
13+
14+
///
15+
/// LedDevice implementation for a lightpack device (http://code.google.com/p/light-pack/)
16+
///
17+
class LedDeviceHyperionUsbasp : public LedDevice
18+
{
19+
public:
20+
// Commands to the Device
21+
enum Commands {
22+
CMD_WRITE_WS2801 = 10,
23+
CMD_WRITE_WS2812 = 11
24+
};
25+
26+
///
27+
/// Constructs the LedDeviceLightpack
28+
///
29+
LedDeviceHyperionUsbasp(uint8_t writeLedsCommand);
30+
31+
///
32+
/// Destructor of the LedDevice; closes the output device if it is open
33+
///
34+
virtual ~LedDeviceHyperionUsbasp();
35+
36+
///
37+
/// Opens and configures the output device
38+
///
39+
/// @return Zero on succes else negative
40+
///
41+
int open();
42+
43+
///
44+
/// Writes the RGB-Color values to the leds.
45+
///
46+
/// @param[in] ledValues The RGB-color per led
47+
///
48+
/// @return Zero on success else negative
49+
///
50+
virtual int write(const std::vector<ColorRgb>& ledValues);
51+
52+
///
53+
/// Switch the leds off
54+
///
55+
/// @return Zero on success else negative
56+
///
57+
virtual int switchOff();
58+
59+
private:
60+
///
61+
/// Test if the device is a Hyperion Usbasp device
62+
///
63+
/// @return Zero on succes else negative
64+
///
65+
int testAndOpen(libusb_device * device);
66+
67+
static libusb_device_handle * openDevice(libusb_device * device);
68+
69+
static std::string getString(libusb_device * device, int stringDescriptorIndex);
70+
71+
private:
72+
/// command to write the leds
73+
const uint8_t _writeLedsCommand;
74+
75+
/// libusb context
76+
libusb_context * _libusbContext;
77+
78+
/// libusb device handle
79+
libusb_device_handle * _deviceHandle;
80+
81+
/// Number of leds
82+
int _ledCount;
83+
84+
/// Usb device identifiers
85+
static uint16_t _usbVendorId;
86+
static uint16_t _usbProductId;
87+
static std::string _usbProductDescription;
88+
};

0 commit comments

Comments
 (0)