mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 01:18:36 +02:00
A2B: Add A2B Tx streaming support
A2B: Add A2BDecoder for streaming wave to A2B device RADA2B: Add functions to configure settings
This commit is contained in:
+52
-202
@@ -1,6 +1,7 @@
|
||||
#include "icsneo/icsneocpp.h"
|
||||
#include "icsneo/communication/encoder.h"
|
||||
#include "icsneo/communication/packet/a2bpacket.h"
|
||||
#include "icsneo/communication/message/a2bmessage.h"
|
||||
#include "icsneo/communication/packetizer.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include "gtest/gtest.h"
|
||||
@@ -11,193 +12,14 @@ using namespace icsneo;
|
||||
class A2BEncoderDecoderTest : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
|
||||
report = [](APIEvent::Type, APIEvent::Severity) {
|
||||
// Unless caught by the test, the packetizer should not throw errors
|
||||
EXPECT_TRUE(false);
|
||||
};
|
||||
packetizer.emplace([this](APIEvent::Type t, APIEvent::Severity s) {
|
||||
report(t, s);
|
||||
});
|
||||
packetEncoder.emplace([this](APIEvent::Type t, APIEvent::Severity s) {
|
||||
report(t, s);
|
||||
});
|
||||
packetDecoder.emplace([this](APIEvent::Type t, APIEvent::Severity s) {
|
||||
report(t, s);
|
||||
});
|
||||
|
||||
A2BPCMSample initialSample = 10 << 8;
|
||||
constructTest(
|
||||
msg1,
|
||||
msg1Encoded,
|
||||
{1,1,0,0,0,0},
|
||||
1,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
0,
|
||||
3,
|
||||
initialSample
|
||||
);
|
||||
|
||||
initialSample = (29 << 16) | (10 << 8);
|
||||
constructTest(
|
||||
msg2,
|
||||
msg2Encoded,
|
||||
{1,0,9,0,0,0},
|
||||
1,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
0,
|
||||
1,
|
||||
initialSample
|
||||
);
|
||||
|
||||
initialSample = (29 << 16) | (10 << 8);
|
||||
constructTest(
|
||||
msg3,
|
||||
msg3Encoded,
|
||||
{2,0,6,0,0xAA,0xFF},
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
0xFFAA,
|
||||
3,
|
||||
initialSample
|
||||
);
|
||||
|
||||
constructTest(
|
||||
msg4,
|
||||
msg4Encoded,
|
||||
{4,0,6,0,0xAA,0xFF},
|
||||
4,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
0xFFAA,
|
||||
0,
|
||||
initialSample
|
||||
);
|
||||
}
|
||||
|
||||
void constructTest(
|
||||
std::shared_ptr<A2BMessage>& testMsg,
|
||||
std::vector<uint8_t>& testMsgEncoded,
|
||||
std::array<uint8_t, 6> encodedHeader,
|
||||
uint8_t numChannels,
|
||||
bool channelSize16,
|
||||
bool monitor,
|
||||
bool txmsg,
|
||||
bool errIndicator,
|
||||
bool syncFrame,
|
||||
uint16_t rfu2,
|
||||
uint32_t numFrames,
|
||||
A2BPCMSample initialSample
|
||||
)
|
||||
{
|
||||
|
||||
testMsg = std::make_shared<A2BMessage>(
|
||||
(uint8_t)(channelSize16 ? 16 : 24),
|
||||
(uint8_t)(channelSize16 ? 2 : 4),
|
||||
numChannels
|
||||
);
|
||||
|
||||
auto addSample = [&](
|
||||
uint8_t channel,
|
||||
A2BMessage::A2BDirection dir
|
||||
) {
|
||||
testMsg->addSample(std::move(initialSample), dir, channel);
|
||||
|
||||
for(size_t i = 0; i < static_cast<size_t>(testMsg->getBytesPerSample()); i++) {
|
||||
testMsgEncoded.push_back(static_cast<uint8_t>(initialSample >> (i * 8)));
|
||||
}
|
||||
|
||||
initialSample++;
|
||||
};
|
||||
|
||||
testMsg->network = Network(Network::NetID::A2B1);
|
||||
testMsg->channelSize16 = channelSize16;
|
||||
testMsg->monitor = monitor;
|
||||
testMsg->txmsg = txmsg;
|
||||
testMsg->errIndicator = errIndicator;
|
||||
testMsg->syncFrame = syncFrame;
|
||||
testMsg->rfu2 = rfu2;
|
||||
|
||||
testMsgEncoded.reserve(
|
||||
HardwareA2BPacket::coreMiniMessageHeaderSize + numFrames * static_cast<size_t>(testMsg->getBytesPerSample())
|
||||
);
|
||||
|
||||
testMsgEncoded.insert(
|
||||
testMsgEncoded.end(),
|
||||
encodedHeader.begin(),
|
||||
encodedHeader.end()
|
||||
); // Insert header
|
||||
appendCoreMiniHeaderOffset(testMsgEncoded);
|
||||
|
||||
for(unsigned int frame = 0; frame < numFrames; frame++) {
|
||||
for(uint8_t channel = 0; channel < testMsg->getNumChannels(); channel++) {
|
||||
|
||||
addSample(channel, A2BMessage::A2BDirection::DownStream);
|
||||
addSample(channel, A2BMessage::A2BDirection::UpStream);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void appendCoreMiniHeaderOffset(std::vector<uint8_t>& buf) {
|
||||
for(
|
||||
size_t i = 0;
|
||||
i < (HardwareA2BPacket::coreMiniMessageHeaderSize - HardwareA2BPacket::a2bHeaderSize);
|
||||
i++
|
||||
) {
|
||||
buf.push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
void decrementEncodedMessageSize(std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() < 6)
|
||||
return;
|
||||
|
||||
uint16_t size = (bytestream[3] << 8) | bytestream[2];
|
||||
|
||||
if(size == 0)
|
||||
return;
|
||||
|
||||
size--;
|
||||
|
||||
bytestream[2] = (uint8_t)size;
|
||||
bytestream[3] = (uint8_t)(size >> 8);
|
||||
}
|
||||
|
||||
void testMessage(std::shared_ptr<A2BMessage>& msg, std::vector<uint8_t>& msgEncoded) {
|
||||
std::vector<uint8_t> bytestream;
|
||||
std::vector<uint8_t> rawPacketBytes;
|
||||
std::shared_ptr<Message> decodeMsg;
|
||||
std::shared_ptr<A2BMessage> decodeA2BMsg;
|
||||
|
||||
EXPECT_TRUE(packetEncoder->encode(*packetizer, bytestream, msg));
|
||||
rawPacketBytes = std::vector<uint8_t>(bytestream.begin() + 6, bytestream.end());
|
||||
|
||||
EXPECT_EQ(rawPacketBytes, msgEncoded);
|
||||
decrementEncodedMessageSize(bytestream);
|
||||
|
||||
EXPECT_TRUE(packetizer->input(bytestream));
|
||||
auto packets = packetizer->output();
|
||||
if(packets.empty()) { EXPECT_TRUE(false);}
|
||||
EXPECT_TRUE(packetDecoder->decode(decodeMsg, packets.back()));
|
||||
decodeA2BMsg = std::static_pointer_cast<A2BMessage>(decodeMsg);
|
||||
|
||||
EXPECT_EQ(*msg, *decodeA2BMsg);
|
||||
packetizer.emplace([this](APIEvent::Type t, APIEvent::Severity s) { report(t, s); });
|
||||
packetEncoder.emplace([this](APIEvent::Type t, APIEvent::Severity s) { report(t, s); });
|
||||
packetDecoder.emplace([this](APIEvent::Type t, APIEvent::Severity s) { report(t, s); });
|
||||
}
|
||||
|
||||
device_eventhandler_t report;
|
||||
@@ -205,31 +27,59 @@ protected:
|
||||
std::optional<Packetizer> packetizer;
|
||||
std::optional<Decoder> packetDecoder;
|
||||
|
||||
std::shared_ptr<A2BMessage> msg1;
|
||||
std::vector<uint8_t> msg1Encoded;
|
||||
std::vector<uint8_t> testBytes =
|
||||
{0xaa, 0x0c, 0x15, 0x00, 0x0b, 0x02, 0x00, 0x00,
|
||||
0x08, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00,
|
||||
0x08, 0x04, 0x00, 0x00};
|
||||
|
||||
std::shared_ptr<A2BMessage> msg2;
|
||||
std::vector<uint8_t> msg2Encoded;
|
||||
|
||||
std::shared_ptr<A2BMessage> msg3;
|
||||
std::vector<uint8_t> msg3Encoded;
|
||||
|
||||
std::shared_ptr<A2BMessage> msg4;
|
||||
std::vector<uint8_t> msg4Encoded;
|
||||
std::vector<uint8_t> recvBytes =
|
||||
{0xaa, 0x00, 0x2a, 0x00, 0x0a, 0x02, 0x02, 0x01,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x08, 0x04,
|
||||
0x00, 0x00};
|
||||
};
|
||||
|
||||
TEST_F(A2BEncoderDecoderTest, ChannelSize16SingleChannel) {
|
||||
testMessage(msg1, msg1Encoded);
|
||||
TEST_F(A2BEncoderDecoderTest, PacketEncoderTest)
|
||||
{
|
||||
std::vector<uint8_t> bytestream;
|
||||
auto messagePtr = std::make_shared<icsneo::A2BMessage>((uint8_t)2, true, 8);
|
||||
messagePtr->network = icsneo::Network::NetID::A2B2;
|
||||
A2BMessage& message = *messagePtr.get();
|
||||
|
||||
message[0][0] = (0x02 << 8) | (0x03);
|
||||
message[0][2] = (0x04 << 8) | (0x08);
|
||||
|
||||
packetEncoder->encode(*packetizer, bytestream, messagePtr);
|
||||
EXPECT_EQ(bytestream, testBytes);
|
||||
}
|
||||
|
||||
TEST_F(A2BEncoderDecoderTest, ChannelSize24MultiChannel) {
|
||||
testMessage(msg2, msg2Encoded);
|
||||
}
|
||||
TEST_F(A2BEncoderDecoderTest, PacketDecoderTest)
|
||||
{
|
||||
std::shared_ptr<icsneo::Message> decodeMsg;
|
||||
std::shared_ptr<icsneo::A2BMessage> message = std::make_shared<icsneo::A2BMessage>((uint8_t)2, true, 8);
|
||||
|
||||
TEST_F(A2BEncoderDecoderTest, ChannelSize24MultiChannelMultiFrame) {
|
||||
testMessage(msg3, msg3Encoded);
|
||||
}
|
||||
message->network = icsneo::Network::NetID::A2B1;
|
||||
message->setTxMsgBit(false);
|
||||
message->setMonitorBit(true);
|
||||
|
||||
TEST_F(A2BEncoderDecoderTest, NoFrames) {
|
||||
testMessage(msg4, msg4Encoded);
|
||||
EXPECT_TRUE(message->setSample(0, 0, (0x02 << 8) | (0x03)));
|
||||
EXPECT_TRUE(message->setSample(2, 0, (0x04 << 8) | (0x08)));
|
||||
|
||||
EXPECT_TRUE(packetizer->input(recvBytes));
|
||||
auto packets = packetizer->output();
|
||||
if(packets.empty()) {
|
||||
EXPECT_TRUE(false);
|
||||
}
|
||||
EXPECT_TRUE(packetDecoder->decode(decodeMsg, packets.back()));
|
||||
auto testMessage = std::dynamic_pointer_cast<icsneo::A2BMessage>(decodeMsg);
|
||||
EXPECT_EQ(message->network, testMessage->network);
|
||||
EXPECT_EQ(message->data, testMessage->data);
|
||||
EXPECT_EQ(message->getNumChannels(), testMessage->getNumChannels());
|
||||
EXPECT_EQ(message->isMonitorMsg(), testMessage->isMonitorMsg());
|
||||
EXPECT_EQ(message->isTxMsg(), testMessage->isTxMsg());
|
||||
EXPECT_EQ(message->isErrIndicator(), testMessage->isErrIndicator());
|
||||
EXPECT_EQ(message->isSyncFrame(), testMessage->isSyncFrame());
|
||||
EXPECT_EQ(message->getRFU2(), testMessage->getRFU2());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user