hyperion.ng/libsrc/leddevice/LedDeviceUdpArtNet.cpp
penfold42 64fc6a9003 Artnet (#440)
* Started implementing artnet/DMX support

It compiles, but certainly wont work just yet

* Fix up packet data and length
correct default udp port

The data looks ok in wireshark

* Code cleanup
Sequence runs from 1..255 not 0
fix universe > 255

* code cleanups and force even number of channels

* Fix potential endianness issue

* added support for 'x' channels per fixture with zero padding
its very basic support for now - it needs better multi universe support
2017-05-26 22:17:12 +02:00

94 lines
2.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <arpa/inet.h>
#include <QHostInfo>
// hyperion local includes
#include "LedDeviceUdpArtNet.h"
LedDeviceUdpArtNet::LedDeviceUdpArtNet(const QJsonObject &deviceConfig)
: ProviderUdp()
{
_deviceReady = init(deviceConfig);
}
bool LedDeviceUdpArtNet::init(const QJsonObject &deviceConfig)
{
_port = 6454;
ProviderUdp::init(deviceConfig);
_artnet_universe = deviceConfig["universe"].toInt(1);
_artnet_channelsPerFixture = deviceConfig["channelsPerFixture"].toInt(3);
return true;
}
LedDevice* LedDeviceUdpArtNet::construct(const QJsonObject &deviceConfig)
{
return new LedDeviceUdpArtNet(deviceConfig);
}
// populates the headers
void LedDeviceUdpArtNet::prepare(const unsigned this_universe, const unsigned this_sequence, unsigned this_dmxChannelCount)
{
// WTF? why do the specs say:
// "This value should be an even number in the range 2 512. "
if (this_dmxChannelCount & 0x1)
{
this_dmxChannelCount++;
}
memcpy (artnet_packet.ID, "Art-Net\0", 8);
artnet_packet.OpCode = htons(0x0050); // OpOutput / OpDmx
artnet_packet.ProtVer = htons(0x000e);
artnet_packet.Sequence = this_sequence;
artnet_packet.Physical = 0;
artnet_packet.SubUni = this_universe & 0xff ;
artnet_packet.Net = (this_universe >> 8) & 0x7f;
artnet_packet.Length = htons(this_dmxChannelCount);
}
int LedDeviceUdpArtNet::write(const std::vector<ColorRgb> &ledValues)
{
int retVal = 0;
int thisUniverse = _artnet_universe;
const uint8_t * rawdata = reinterpret_cast<const uint8_t *>(ledValues.data());
/*
This field is incremented in the range 0x01 to 0xff to allow the receiving node to resequence packets.
The Sequence field is set to 0x00 to disable this feature.
*/
if (_artnet_seq++ == 0)
{
_artnet_seq = 1;
}
int dmxIdx = 0; // offset into the current dmx packet
memset(artnet_packet.raw, 0, sizeof(artnet_packet.raw));
for (int ledIdx = 0; ledIdx < _ledRGBCount; ledIdx++)
{
artnet_packet.Data[dmxIdx++] = rawdata[ledIdx];
if ( (ledIdx % 3 == 2) && (ledIdx > 0) )
{
dmxIdx += (_artnet_channelsPerFixture-3);
}
// is this the last byte of last packet || last byte of other packets
if ( (ledIdx == _ledRGBCount-1) || (dmxIdx >= DMX_MAX) )
{
prepare(thisUniverse, _artnet_seq, dmxIdx);
retVal &= writeBytes(18 + std::min(dmxIdx, DMX_MAX), artnet_packet.raw);
memset(artnet_packet.raw, 0, sizeof(artnet_packet.raw));
thisUniverse ++;
dmxIdx = 0;
}
}
return retVal;
}