stream IO for the API
This commit is contained in:
parent
8e41fc72c2
commit
8f3d704d5a
|
@ -6,8 +6,15 @@ add_library(ENTTEC::Pro ALIAS ${PROJECT_NAME})
|
|||
target_sources(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
pro.h
|
||||
PRIVATE
|
||||
pro.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
LCP::BufferStream
|
||||
LCP::DMX
|
||||
)
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${PROJECT_VERSION})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
pro.cpp
|
||||
|
||||
Copyright (c) 2023 Kevin Matz (kevin.matz@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "dmx.h"
|
||||
#include "pro.h"
|
||||
|
||||
namespace ENTTEC::Pro {
|
||||
|
||||
void MsgProgramFlashPageRequest::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
if (stream->available() < sizeof(page))
|
||||
return stream->setstate(std::ios_base::failbit);
|
||||
|
||||
stream->read(page, sizeof(page));
|
||||
|
||||
if (!stream->available())
|
||||
stream->setstate(std::ios_base::eofbit);
|
||||
};
|
||||
|
||||
|
||||
void MsgProgramFlashPageRequest::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
stream->write(page, sizeof(page));
|
||||
};
|
||||
|
||||
|
||||
void MsgProgramFlashPageReply::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
uint8_t buffer[sizeof(SUCCESS_OK)];
|
||||
success = false;
|
||||
|
||||
if (stream->available() < sizeof(buffer))
|
||||
return stream->setstate(std::ios_base::failbit);
|
||||
|
||||
stream->read(buffer, sizeof(buffer));
|
||||
|
||||
if (!stream->available())
|
||||
stream->setstate(std::ios_base::eofbit);
|
||||
|
||||
success = !std::memcmp(buffer, SUCCESS_OK, sizeof(buffer));
|
||||
};
|
||||
|
||||
|
||||
void MsgProgramFlashPageReply::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
if (success)
|
||||
stream->write(reinterpret_cast<const uint8_t*>(SUCCESS_OK), sizeof(SUCCESS_OK));
|
||||
else
|
||||
stream->write(reinterpret_cast<const uint8_t*>(SUCCESS_FAIL), sizeof(SUCCESS_FAIL));
|
||||
};
|
||||
|
||||
|
||||
void MsgGetWidgetParametersRequest::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
*stream >> size;
|
||||
};
|
||||
|
||||
|
||||
void MsgGetWidgetParametersRequest::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
*stream << size;
|
||||
};
|
||||
|
||||
|
||||
void MsgGetWidgetParametersReply::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
*stream >> fw_rev;
|
||||
*stream >> fw_type;
|
||||
*stream >> break_time;
|
||||
*stream >> mab_time;
|
||||
*stream >> rate;
|
||||
if (!stream->eof()) {
|
||||
std::vector<uint8_t> buffer;
|
||||
stream->read(buffer.data(), USER_CONFIGURATION_MAX);
|
||||
std::copy(buffer.begin(), buffer.end(), std::back_inserter(user_data));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void MsgGetWidgetParametersReply::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
*stream << fw_rev;
|
||||
*stream << fw_type;
|
||||
*stream << break_time;
|
||||
*stream << mab_time;
|
||||
*stream << rate;
|
||||
stream->write(user_data.data(), std::min(user_data.size(), USER_CONFIGURATION_MAX));
|
||||
};
|
||||
|
||||
|
||||
void MsgSetWidgetParametersRequest::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
uint16_t size;
|
||||
*stream >> size;
|
||||
*stream >> break_time;
|
||||
*stream >> mab_time;
|
||||
*stream >> rate;
|
||||
if (size)
|
||||
{
|
||||
std::vector<uint8_t> buffer;
|
||||
stream->read(buffer.data(), USER_CONFIGURATION_MAX);
|
||||
std::copy(buffer.begin(), buffer.end(), std::back_inserter(user_data));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void MsgSetWidgetParametersRequest::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
*stream << (uint16_t)user_data.size();
|
||||
*stream << break_time;
|
||||
*stream << mab_time;
|
||||
*stream << rate;
|
||||
stream->write(user_data.data(), std::min(user_data.size(), USER_CONFIGURATION_MAX));
|
||||
};
|
||||
|
||||
|
||||
void MsgRecievedDmxPacket::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
*stream >> rx_corrupted;
|
||||
stream->read(data.data(), DMX::E111_LAST_SLOT + 1);
|
||||
};
|
||||
|
||||
|
||||
void MsgRecievedDmxPacket::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
*stream << rx_corrupted;
|
||||
stream->write(data.data(), std::min(data.size(), DMX::E111_LAST_SLOT + 1));
|
||||
};
|
||||
|
||||
|
||||
void MsgOutputOnlySendDMX::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
stream->read(data.data(), DMX::E111_LAST_SLOT + 1);
|
||||
};
|
||||
|
||||
|
||||
void MsgOutputOnlySendDMX::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
stream->write(data.data(), std::min(data.size(), DMX::E111_LAST_SLOT + 1));
|
||||
for (size_t i = data.size(); i <= DMX_LAST_SLOT_MIN; i++)
|
||||
*stream << (uint8_t) 0;
|
||||
};
|
||||
|
||||
|
||||
void MsgSendRDMData::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
stream->read(data.data(), DMX::E111_LAST_SLOT + 1);
|
||||
};
|
||||
|
||||
|
||||
void MsgSendRDMData::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
stream->write(data.data(), std::min(data.size(), DMX::E111_LAST_SLOT + 1));
|
||||
};
|
||||
|
||||
|
||||
void MsgRecieveDMXOnChange::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
uint8_t val;
|
||||
*stream >> val;
|
||||
if (val)
|
||||
mode = RxNotifyOnChange;
|
||||
else
|
||||
mode = RxNotifyAlways;
|
||||
};
|
||||
|
||||
|
||||
void MsgRecieveDMXOnChange::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
if (mode == RxNotifyOnChange)
|
||||
*stream << (uint8_t)1;
|
||||
else
|
||||
*stream << (uint8_t)0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
void MsgRecievedDMXChanged::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
*stream >> start;
|
||||
stream->read(changed, sizeof(changed));
|
||||
stream->read(data.data(), 40);
|
||||
};
|
||||
|
||||
|
||||
void MsgRecievedDMXChanged::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
*stream << start;
|
||||
stream->write(changed, sizeof(changed));
|
||||
stream->write(data.data(), std::min(data.size(), (size_t)40));
|
||||
};
|
||||
|
||||
|
||||
void MsgGetWidgetSerialReply::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
*stream >> serial;
|
||||
};
|
||||
|
||||
|
||||
void MsgGetWidgetSerialReply::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
*stream << serial;
|
||||
};
|
||||
|
||||
|
||||
void MsgSendRDMDiscovery::iStream(std::shared_ptr<bufferstream> stream)
|
||||
{
|
||||
stream->read(request, sizeof(request));
|
||||
};
|
||||
|
||||
|
||||
void MsgSendRDMDiscovery::oStream(std::shared_ptr<bufferstream> stream) const
|
||||
{
|
||||
stream->write(request, sizeof(request));
|
||||
};
|
||||
|
||||
} // namespace ENTTEC::Pro
|
|
@ -23,23 +23,26 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
#include <bufferstream.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace ENTTEC {
|
||||
namespace PRO {
|
||||
namespace ENTTEC::Pro {
|
||||
|
||||
struct ApplicationMessage;
|
||||
struct MessageData;
|
||||
|
||||
/**
|
||||
* @brief Application Message Format
|
||||
*
|
||||
* \cite DMXUSBPro The PC based application program communicates with the Widget.
|
||||
*/
|
||||
struct Message {
|
||||
uint8_t label; //!< Label to identify the type of message.
|
||||
std::shared_ptr<ApplicationMessage> message; //!< Data
|
||||
struct Message
|
||||
{
|
||||
uint8_t label; //!< "OpCode" Label to identify the type of message.
|
||||
std::shared_ptr<MessageData> data; //!< Data
|
||||
};
|
||||
|
||||
const uint8_t START_DELIMITER = 0x7e; //!< Start of message delimiter
|
||||
|
@ -79,11 +82,12 @@ enum MESSAGE_LABEL {
|
|||
|
||||
|
||||
/**
|
||||
* @brief The ApplicationMessage class
|
||||
* @brief The MessageData class
|
||||
*
|
||||
* Base type of each message data.
|
||||
*/
|
||||
struct ApplicationMessage
|
||||
struct MessageData
|
||||
: public streamable
|
||||
{
|
||||
};
|
||||
|
||||
|
@ -95,8 +99,11 @@ struct ApplicationMessage
|
|||
* enable reprogramming of the Widget firmware.
|
||||
*/
|
||||
struct MsgReprogramFirmware
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
size_t streamSize() const override { return 0; };
|
||||
void iStream(std::shared_ptr<bufferstream>) override {};
|
||||
void oStream(std::shared_ptr<bufferstream>) const override{};
|
||||
};
|
||||
|
||||
|
||||
|
@ -108,9 +115,13 @@ struct MsgReprogramFirmware
|
|||
* the firmware binary file.
|
||||
*/
|
||||
struct MsgProgramFlashPageRequest
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
uint8_t page[64]; //!< One page of firmware binary file.
|
||||
|
||||
size_t streamSize() const override { return 64; };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -121,9 +132,13 @@ struct MsgProgramFlashPageRequest
|
|||
* Program Flash Page request.
|
||||
*/
|
||||
struct MsgProgramFlashPageReply
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
bool success; //!< Success character array product
|
||||
bool success; //!< Success character array product
|
||||
|
||||
size_t streamSize() const override { return 4; };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
const char SUCCESS_OK[4] = {'T','R','U','E'}; //!< Firmware page write success
|
||||
|
@ -136,12 +151,16 @@ const char SUCCESS_FAIL[4] = {'F','A','L','S'}; //!< Firmware page write failure
|
|||
* \cite DMXUSBPro This message requests the Widget configuration.
|
||||
*/
|
||||
struct MsgGetWidgetParametersRequest
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
uint16_t user_configuration_size = 0; //!< user configuration size in bytes
|
||||
uint16_t size = 0; //!< user configuration size in bytes
|
||||
|
||||
size_t streamSize() const override { return 2; };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
const uint16_t USER_CONFIGURATION_MAX = 508; //!< maximum user configuration size
|
||||
const size_t USER_CONFIGURATION_MAX = 508; //!< maximum user configuration size
|
||||
|
||||
|
||||
/**
|
||||
|
@ -151,7 +170,7 @@ const uint16_t USER_CONFIGURATION_MAX = 508; //!< maximum user configuration siz
|
|||
* Widget Parameters request.
|
||||
*/
|
||||
struct MsgGetWidgetParametersReply
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
union {
|
||||
uint16_t version;
|
||||
|
@ -164,6 +183,10 @@ struct MsgGetWidgetParametersReply
|
|||
uint8_t mab_time; //!< interval count of the DMX output MARK AFTER BREAK
|
||||
uint8_t rate; //!< DMX output rate in packets per second.
|
||||
std::vector<uint8_t> user_data; //!< user defined configuration data
|
||||
|
||||
size_t streamSize() const override { return 5 + user_data.size(); };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
const float DMX_BREAK_INTERVAL = 10.67; //!< microseconds, resolution of the BREAK interval
|
||||
|
@ -184,12 +207,16 @@ const uint8_t DMX_RATE_MAX = 40; //!< minimum DMX refresh rate
|
|||
* \cite DMXUSBPro This message sets the Widget configuration.
|
||||
*/
|
||||
struct MsgSetWidgetParametersRequest
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
uint8_t break_time; //!< interval count of the DMX output BREAK
|
||||
uint8_t mab_time; //!< interval count of the DMX output MARK AFTER BREAK
|
||||
uint8_t rate; //!< DMX output rate in packets per second.
|
||||
std::vector<uint8_t> user_data; //!< user defined configuration data
|
||||
|
||||
size_t streamSize() const override { return 5 + user_data.size(); };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -201,7 +228,7 @@ struct MsgSetWidgetParametersRequest
|
|||
* mode is 'Send always'.
|
||||
*/
|
||||
struct MsgRecievedDmxPacket
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
union {
|
||||
uint8_t rx_corrupted; //!< When this is 0, the DMX data is valid.
|
||||
|
@ -211,9 +238,15 @@ struct MsgRecievedDmxPacket
|
|||
};
|
||||
};
|
||||
std::vector<uint8_t> data; //!< Received DMX data beginning with the start code.
|
||||
|
||||
size_t streamSize() const override { return 1 + data.size(); };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
|
||||
const size_t DMX_LAST_SLOT_MIN = 24; //!< length of the shortest supported universe
|
||||
|
||||
/**
|
||||
* @brief 8. Output Only Send DMX Packet Request (Label=6)
|
||||
*
|
||||
|
@ -221,12 +254,15 @@ struct MsgRecievedDmxPacket
|
|||
* of the Widget DMX port at the configured DMX output rate.
|
||||
*/
|
||||
struct MsgOutputOnlySendDMX
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
std::vector<uint8_t> data; //!< DMX data to send, beginning with the start code.
|
||||
|
||||
size_t streamSize() const override { return std::max(data.size(), DMX_LAST_SLOT_MIN + 1); };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
const uint8_t DMX_LAST_SLOT_MIN = 24; //!< length of the shortest supported universe
|
||||
|
||||
|
||||
/**
|
||||
|
@ -237,9 +273,13 @@ const uint8_t DMX_LAST_SLOT_MIN = 24; //!< length of the shortest supporte
|
|||
* DMX packets can be received.
|
||||
*/
|
||||
struct MsgSendRDMData
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
std::vector<uint8_t> data; //!< RDM data to send, beginning with the start code.
|
||||
|
||||
size_t streamSize() const override { return data.size(); };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -259,9 +299,13 @@ enum DMX_RX_MODE {
|
|||
* by sending this message.
|
||||
*/
|
||||
struct MsgRecieveDMXOnChange
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
DMX_RX_MODE mode = RxNotifyAlways; //!< Always (default), or OnChange
|
||||
|
||||
size_t streamSize() const override { return 1; };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -273,11 +317,15 @@ struct MsgRecieveDMXOnChange
|
|||
* Change mode is 'Send on data change only'.
|
||||
*/
|
||||
struct MsgRecievedDMXChanged
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
uint8_t start; //!< Start changed byte number.
|
||||
uint8_t changed[5]; //!< Changed bit array.
|
||||
std::vector<uint8_t> data; //!< Changed DMX data byte data.
|
||||
|
||||
size_t streamSize() const override { return 6 + data.size(); };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -287,8 +335,11 @@ struct MsgRecievedDMXChanged
|
|||
* \cite DMXUSBPro This message requests the Widget serial number.
|
||||
*/
|
||||
struct MsgGetWidgetSerialRequest
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
size_t streamSize() const override { return 0; };
|
||||
void iStream(std::shared_ptr<bufferstream>) override {};
|
||||
void oStream(std::shared_ptr<bufferstream>) const override{};
|
||||
};
|
||||
|
||||
|
||||
|
@ -299,9 +350,13 @@ struct MsgGetWidgetSerialRequest
|
|||
* Serial Number request.
|
||||
*/
|
||||
struct MsgGetWidgetSerialReply
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
uint32_t serial; //!< BCD serial number.
|
||||
|
||||
size_t streamSize() const override { return 4; };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
|
||||
|
@ -312,10 +367,13 @@ struct MsgGetWidgetSerialReply
|
|||
* out of the Widget DMX port, and then receive an RDM Discovery Response.
|
||||
*/
|
||||
struct MsgSendRDMDiscovery
|
||||
: public ApplicationMessage
|
||||
: public MessageData
|
||||
{
|
||||
uint8_t request[38]; //!< DISC_UNIQUE_BRANCH RDM request packet to send.
|
||||
|
||||
size_t streamSize() const override { return 38; };
|
||||
void iStream(std::shared_ptr<bufferstream>) override;
|
||||
void oStream(std::shared_ptr<bufferstream>) const override;
|
||||
};
|
||||
|
||||
} // namespace PRO
|
||||
} // namespace ENTTEC
|
||||
} // namespace ENTTEC::Pro
|
||||
|
|
Loading…
Reference in New Issue