Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for OpenDeck boards #1746

Open
wants to merge 41 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
358bcf0
add support for opendeck boards
paradajz Sep 29, 2021
55ba838
add tests for opendeck widget
paradajz Oct 23, 2021
d9b5ec1
implement fps limiting for opendeck device
paradajz Jan 23, 2022
62ccfb8
Update plugins/usbpro/WidgetDetectorThreadTest.cpp
paradajz Feb 7, 2022
5daabf6
Update plugins/usbpro/WidgetDetectorThreadTest.cpp
paradajz Feb 7, 2022
3478625
Update plugins/usbpro/OpenDeckDevice.cpp
paradajz Feb 7, 2022
b34fa1a
Update plugins/usbpro/OpenDeckDevice.cpp
paradajz Feb 7, 2022
c619740
OpenDeckDevice.cpp: fail immediately for set param req
paradajz Feb 7, 2022
3ab8b34
OpenDeck: update copyrights
paradajz Feb 7, 2022
cc5923a
OpenDeckWidget: use sizeof instead of hardcoded value
paradajz Feb 7, 2022
6f552fa
WidgetDetectorThreadTest.cpp: fix line length
paradajz Feb 7, 2022
50f85c1
Update plugins/usbpro/OpenDeckDevice.cpp
paradajz Feb 7, 2022
fb735da
OpenDeckWidget: rework sending of data
paradajz Feb 7, 2022
fe204c8
Update plugins/usbpro/UsbSerialPlugin.cpp
paradajz Feb 7, 2022
5bfb82c
OpenDeckDevice.cpp: fix retrieving firmware version
paradajz Feb 7, 2022
6e33701
OpenDeckDevice.cpp: rework serial number retrieval
paradajz Feb 7, 2022
20d2af9
Update plugins/usbpro/UsbSerialPlugin.cpp
paradajz Feb 8, 2022
b8595c4
Update plugins/usbpro/OpenDeckDevice.cpp
paradajz Feb 8, 2022
ba99cd3
OpenDeckDevice.cpp: more informative failure when setting params
paradajz Feb 8, 2022
f13a858
Update plugins/usbpro/OpenDeckWidget.cpp
paradajz Feb 8, 2022
713ca0f
Update plugins/usbpro/OpenDeckWidget.cpp
paradajz Feb 8, 2022
de29bcc
OpenDeckDevice.cpp: improve func doc
paradajz Feb 8, 2022
6076116
OpenDeckDevice.cpp: remove serial nr prefix and make it uppercase
paradajz Feb 8, 2022
04dc0c6
Update plugins/usbpro/OpenDeckWidget.cpp
paradajz Mar 15, 2022
3fb162f
Update plugins/usbpro/OpenDeckWidget.cpp
paradajz Mar 15, 2022
9fa3e5b
Update plugins/usbpro/OpenDeckWidget.cpp
paradajz Mar 15, 2022
f80b3dc
Update plugins/usbpro/OpenDeckWidget.cpp
paradajz Mar 15, 2022
3ca240c
format: extend ToHex with uppercase flag
paradajz Mar 15, 2022
cdfbd16
OpenDeckDevice: use ToHex with uppercase flag
paradajz Mar 15, 2022
2c0487f
Test the new uppercase option for ToHex
peternewman Mar 15, 2022
3a3cd0a
Trivial whitespace tidy
peternewman Mar 15, 2022
73e64d2
Minor spelling tweak
peternewman Mar 15, 2022
c9682d4
Minor grammar tweak
peternewman Mar 15, 2022
74c1149
OpenDeckDevice: remove unused arg from constructor doc
paradajz Mar 15, 2022
75cba45
OpenDeckWidget: naming consistency
paradajz Mar 15, 2022
829adbf
OpenDeckDevice: handle token bucket in Widget class
paradajz Mar 15, 2022
6013515
misc whitespace
paradajz Mar 15, 2022
4369fd8
Ignore a codespell false positive due to line wrapping
peternewman Mar 16, 2022
0b83176
whitespace
paradajz Mar 16, 2022
d6142ee
opendeck: token bucket handling alt approach
paradajz Mar 16, 2022
161435b
fix new tests
paradajz Mar 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .codespellignorelines
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,4 @@ import java.nio.ByteOrder;
byte[] header = ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(headerContent).array();
int headerValue = ByteBuffer.wrap(header).order(ByteOrder.nativeOrder()).getInt();
# This is a very bodgy workaround to the fact that the pip install of the archive doesn't seem to work properly now on Travis
"uest\032\036.ola.rpc.STREAMING_NO_RESPONSEB\006\200\001"
2 changes: 1 addition & 1 deletion common/utils/StringUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ bool StripSuffix(string *s, const string &suffix) {

string IntToHexString(unsigned int i, unsigned int width) {
strings::_ToHex<unsigned int> v = strings::_ToHex<unsigned int>(
i, static_cast<int>(width), true);
i, static_cast<int>(width), true, false);
ostringstream str;
str << v;
return str.str();
Expand Down
50 changes: 50 additions & 0 deletions common/utils/StringUtilsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,56 @@ void StringUtilsTest::testIntToHexString() {
str << ToHex((uint16_t)0xABCD, false);
OLA_ASSERT_EQ(string("abcd"), str.str());
str.str("");

// Value case option - lower
str << ToHex((uint8_t)0, true, false);
OLA_ASSERT_EQ(string("0x00"), str.str());
str.str("");

str << ToHex((uint8_t)1, true, false);
OLA_ASSERT_EQ(string("0x01"), str.str());
str.str("");

str << ToHex((uint8_t)255, true, false);
OLA_ASSERT_EQ(string("0xff"), str.str());
str.str("");

str << ToHex((uint8_t)0x42, false, false);
OLA_ASSERT_EQ(string("42"), str.str());
str.str("");

str << ToHex((uint16_t)0xABCD, false, false);
OLA_ASSERT_EQ(string("abcd"), str.str());
str.str("");

str << ToHex((uint32_t)0xDEADBEEF, false, false);
OLA_ASSERT_EQ(string("deadbeef"), str.str());
str.str("");

// Value case option - upper
str << ToHex((uint8_t)0, true, true);
OLA_ASSERT_EQ(string("0x00"), str.str());
str.str("");

str << ToHex((uint8_t)1, true, true);
OLA_ASSERT_EQ(string("0x01"), str.str());
str.str("");

str << ToHex((uint8_t)255, true, true);
OLA_ASSERT_EQ(string("0xFF"), str.str());
str.str("");

str << ToHex((uint8_t)0x42, false, true);
OLA_ASSERT_EQ(string("42"), str.str());
str.str("");

str << ToHex((uint16_t)0xABCD, false, true);
OLA_ASSERT_EQ(string("ABCD"), str.str());
str.str("");

str << ToHex((uint32_t)0xDEADBEEF, false, true);
OLA_ASSERT_EQ(string("DEADBEEF"), str.str());
str.str("");
}


Expand Down
11 changes: 9 additions & 2 deletions include/ola/strings/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,18 @@ std::string IntToString(unsigned int i);
* @tparam T the type of value to convert
* @param v the value to convert
* @param prefix show the 0x prefix
* @param uppercase make the value uppercase
* @return A _ToHex struct representing the value, output it to an ostream to
* use it.
* @note We only currently support unsigned ints due to a lack of requirement
* for anything else
*/
template<typename T>
_ToHex<T> ToHex(T v, bool prefix = true) {
return _ToHex<T>(v, (std::numeric_limits<T>::digits / HEX_BIT_WIDTH), prefix);
_ToHex<T> ToHex(T v, bool prefix = true, bool uppercase = false) {
return _ToHex<T>(v,
(std::numeric_limits<T>::digits / HEX_BIT_WIDTH),
prefix,
uppercase);
}

/**
Expand All @@ -80,6 +84,9 @@ std::ostream& operator<<(std::ostream &out, const ola::strings::_ToHex<T> &i) {
if (i.prefix) {
out << "0x";
}
if (i.uppercase) {
out << std::uppercase;
}
out << std::setw(i.width) << std::hex << std::setfill('0')
<< ola::strings::_HexCast(i.value);
out.flags(flags); // Put the format flags back to normal
Expand Down
6 changes: 4 additions & 2 deletions include/ola/strings/FormatPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,17 @@ enum { HEX_BIT_WIDTH = 4 };
template<typename T>
struct _ToHex {
public:
_ToHex(T v, int _width, bool _prefix)
_ToHex(T v, int _width, bool _prefix, bool _uppercase)
: width(_width),
value(v),
prefix(_prefix) {
prefix(_prefix),
uppercase(_uppercase) {
}

int width; // setw takes an int
T value;
bool prefix;
bool uppercase;
};

inline uint32_t _HexCast(uint8_t v) { return v; }
Expand Down
4 changes: 4 additions & 0 deletions plugins/usbpro/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ plugins_usbpro_libolausbprowidget_la_SOURCES = \
plugins/usbpro/EnttecUsbProWidgetImpl.h \
plugins/usbpro/GenericUsbProWidget.cpp \
plugins/usbpro/GenericUsbProWidget.h \
plugins/usbpro/OpenDeckWidget.cpp \
plugins/usbpro/OpenDeckWidget.h \
plugins/usbpro/RobeWidget.cpp \
plugins/usbpro/RobeWidget.h \
plugins/usbpro/RobeWidgetDetector.cpp \
Expand Down Expand Up @@ -53,6 +55,8 @@ plugins_usbpro_libolausbpro_la_SOURCES = \
plugins/usbpro/DmxTriDevice.h \
plugins/usbpro/DmxterDevice.cpp \
plugins/usbpro/DmxterDevice.h \
plugins/usbpro/OpenDeckDevice.cpp \
plugins/usbpro/OpenDeckDevice.h \
plugins/usbpro/RobeDevice.cpp \
plugins/usbpro/RobeDevice.h \
plugins/usbpro/UltraDMXProDevice.cpp \
Expand Down
239 changes: 239 additions & 0 deletions plugins/usbpro/OpenDeckDevice.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* OpenDeckDevice.cpp
* An OpenDeck Device
* Copyright (C) 2022 Igor Petrovic
*
* This device creates a single OpenDeck output port
*/

#include <iomanip>
#include <ios>
#include <iostream>
#include <string>

#include "common/rpc/RpcController.h"
#include "ola/Callback.h"
#include "ola/Constants.h"
#include "ola/strings/Format.h"
#include "plugins/usbpro/OpenDeckDevice.h"
#include "plugins/usbpro/UsbProWidgetDetector.h"

namespace ola {
namespace plugin {
namespace usbpro {

using ola::plugin::usbpro::Request;
using ola::plugin::usbpro::Reply;
using ola::rpc::RpcController;
using ola::utils::SplitUInt16;
using ola::strings::ToHex;
using std::string;

/*
* Create a new device
* @param owner the plugin that owns this device
* @param name the device name
*/
OpenDeckDevice::OpenDeckDevice(ola::PluginAdaptor *plugin_adaptor,
ola::AbstractPlugin *owner,
const string &name,
OpenDeckWidget *widget,
OLA_UNUSED uint16_t esta_id,
OLA_UNUSED uint16_t device_id,
uint32_t serial,
uint16_t firmware_version,
unsigned int fps_limit):
UsbSerialDevice(owner, name, widget),
m_opendeck_widget(widget),
m_serial(),
m_got_parameters(false),
m_break_time(0),
m_mab_time(0),
m_rate(0) {
// Serial number is stored as a series of 4 bytes.
// Display the serial in hex format so that it
// matches (partially) with the USB serial number.
std::ostringstream str;
str << ToHex(serial, false, true);
m_serial = str.str();
str.str("");

// Firmware version is stored in major.minor format.
// This scheme uses the following encoding:
// MMMMMMMM mmmmmmmm
// M: major
// m: minor
uint8_t major;
uint8_t minor;

SplitUInt16(firmware_version, &major, &minor);

str << "Serial #: " << m_serial << ", firmware "
<< static_cast<int>(major) << "." << static_cast<int>(minor);

m_opendeck_widget->GetParameters(NewSingleCallback(
this,
&OpenDeckDevice::UpdateParams));

// add the output port
OutputPort *output_port = new OpenDeckOutputPort(
this,
m_opendeck_widget,
0,
str.str(),
plugin_adaptor->WakeUpTime(),
5, // allow up to 5 burst frames
fps_limit);
AddPort(output_port);
}


/*
* Stop this device
*/
void OpenDeckDevice::PrePortStop() {
m_opendeck_widget->Stop();
}


/*
* Handle device config messages
* @param controller An RpcController
* @param request the request data
* @param response the response to return
* @param done the closure to call once the request is complete
*/
void OpenDeckDevice::Configure(RpcController *controller,
const string &request,
string *response,
ConfigureCallback *done) {
Request request_pb;
if (!request_pb.ParseFromString(request)) {
controller->SetFailed("Invalid Request");
done->Run();
return;
}

switch (request_pb.type()) {
case ola::plugin::usbpro::Request::USBPRO_PARAMETER_REQUEST:
HandleParametersRequest(controller, &request_pb, response, done);
break;
case ola::plugin::usbpro::Request::USBPRO_SERIAL_REQUEST:
HandleSerialRequest(controller, &request_pb, response, done);
break;
default:
controller->SetFailed("Invalid Request");
done->Run();
}
}


/**
* Update the cached param values
*/
void OpenDeckDevice::UpdateParams(bool status,
const usb_pro_parameters &params) {
if (status) {
m_got_parameters = true;
m_break_time = params.break_time;
m_mab_time = params.mab_time;
m_rate = params.rate;
}
}


/*
* Handle a parameter request. On OpenDeck devices, setting the parameters
* isn't supported. OpenDeck firmware runs on various architectures and
* microcontrollers, and on some of them it's not really feasible to make
* the timings configurable. Instead, firmware switches between 100000 and
* 250000 baudrate to generate the correct timings. Failure is indicated
* to the requester in this case. Fetching the parameters and returning
* them to the client works normally.
*/
void OpenDeckDevice::HandleParametersRequest(RpcController *controller,
const Request *request,
string *response,
ConfigureCallback *done) {
if (request->has_parameters() &&
(request->parameters().has_break_time() ||
request->parameters().has_mab_time() ||
request->parameters().has_rate())) {
peternewman marked this conversation as resolved.
Show resolved Hide resolved
controller->SetFailed("Parameters on this device are read-only.");
done->Run();
return;
}

m_opendeck_widget->GetParameters(NewSingleCallback(
this,
&OpenDeckDevice::HandleParametersResponse,
controller,
response,
done));
}


/**
* Handle the GetParameters response
*/
void OpenDeckDevice::HandleParametersResponse(
RpcController *controller,
string *response,
ConfigureCallback *done,
bool status,
const usb_pro_parameters &params) {
if (!status) {
controller->SetFailed("GetParameters failed");
} else {
UpdateParams(true, params);
Reply reply;
reply.set_type(ola::plugin::usbpro::Reply::USBPRO_PARAMETER_REPLY);
ola::plugin::usbpro::ParameterReply *parameters_reply =
reply.mutable_parameters();

parameters_reply->set_firmware_high(params.firmware_high);
parameters_reply->set_firmware(params.firmware);
parameters_reply->set_break_time(params.break_time);
parameters_reply->set_mab_time(params.mab_time);
parameters_reply->set_rate(params.rate);
reply.SerializeToString(response);
}
done->Run();
}


/*
* Handle a Serial number Configure RPC. We can just return the cached number.
*/
void OpenDeckDevice::HandleSerialRequest(
RpcController *controller,
const Request *request,
string *response,
ConfigureCallback *done) {
Reply reply;
reply.set_type(ola::plugin::usbpro::Reply::USBPRO_SERIAL_REPLY);
ola::plugin::usbpro::SerialNumberReply *serial_reply =
reply.mutable_serial_number();
serial_reply->set_serial(m_serial);
reply.SerializeToString(response);
done->Run();
(void) controller;
(void) request;
}
} // namespace usbpro
} // namespace plugin
} // namespace ola
Loading