MDIO: Network support
parent
0de23f2817
commit
f5096b879c
|
|
@ -11,3 +11,6 @@ third-party/concurrentqueue/tests
|
|||
.vs
|
||||
.cache
|
||||
*.wav
|
||||
*.orig
|
||||
examples/csharp/bin
|
||||
examples/csharp/obj
|
||||
|
|
@ -245,6 +245,7 @@ set(SRC_FILES
|
|||
communication/packet/wivicommandpacket.cpp
|
||||
communication/packet/i2cpacket.cpp
|
||||
communication/packet/linpacket.cpp
|
||||
communication/packet/mdiopacket.cpp
|
||||
communication/packet/scriptstatuspacket.cpp
|
||||
communication/packet/componentversionpacket.cpp
|
||||
communication/packet/supportedfeaturespacket.cpp
|
||||
|
|
@ -469,6 +470,7 @@ if(LIBICSNEO_BUILD_TESTS)
|
|||
test/i2cencoderdecodertest.cpp
|
||||
test/linencoderdecodertest.cpp
|
||||
test/a2bencoderdecodertest.cpp
|
||||
test/mdioencoderdecodertest.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(libicsneo-tests gtest gtest_main)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "icsneo/communication/message/flexray/control/flexraycontrolmessage.h"
|
||||
#include "icsneo/communication/message/i2cmessage.h"
|
||||
#include "icsneo/communication/message/linmessage.h"
|
||||
#include "icsneo/communication/message/mdiomessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/communication/packet/canpacket.h"
|
||||
|
|
@ -28,6 +29,7 @@
|
|||
#include "icsneo/communication/packet/linpacket.h"
|
||||
#include "icsneo/communication/packet/componentversionpacket.h"
|
||||
#include "icsneo/communication/packet/supportedfeaturespacket.h"
|
||||
#include "icsneo/communication/packet/mdiopacket.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace icsneo;
|
||||
|
|
@ -166,6 +168,18 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
|||
msg.network = packet->network;
|
||||
return true;
|
||||
}
|
||||
case Network::Type::MDIO: {
|
||||
result = HardwareMDIOPacket::DecodeToMessage(packet->data);
|
||||
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; // A nullptr was returned, the packet was not long enough to decode
|
||||
}
|
||||
|
||||
MDIOMessage& msg = *static_cast<MDIOMessage*>(result.get());
|
||||
msg.network = packet->network;
|
||||
return true;
|
||||
}
|
||||
case Network::Type::Internal: {
|
||||
switch(packet->network.getNetID()) {
|
||||
case Network::NetID::Reset_Status: {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "icsneo/communication/message/i2cmessage.h"
|
||||
#include "icsneo/communication/packet/a2bpacket.h"
|
||||
#include "icsneo/communication/packet/linpacket.h"
|
||||
#include "icsneo/communication/packet/mdiopacket.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
|
|
@ -108,6 +109,18 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
|||
}
|
||||
break;
|
||||
} // End of Network::Type::LIN
|
||||
case Network::Type::MDIO: {
|
||||
auto mdiomsg = std::dynamic_pointer_cast<MDIOMessage>(message);
|
||||
if(!mdiomsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
buffer = &result;
|
||||
if(!HardwareMDIOPacket::EncodeFromMessage(*mdiomsg, result, report)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
} // End of Network::Type::MDIO
|
||||
default:
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
#include "icsneo/communication/packet/mdiopacket.h"
|
||||
|
||||
namespace icsneo
|
||||
{
|
||||
|
||||
const size_t HardwareMDIOPacket::mdioDataSize = 2;
|
||||
|
||||
std::shared_ptr<Message> HardwareMDIOPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream)
|
||||
{
|
||||
auto msg = std::make_shared<MDIOMessage>();
|
||||
const HardwareMDIOPacket* packet = reinterpret_cast<const HardwareMDIOPacket*>(bytestream.data());
|
||||
if((sizeof(HardwareMDIOPacket) != (bytestream.size())) || (packet->length != 0))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
msg->network = Network::GetNetIDFromCoreMiniNetwork(static_cast<Network::CoreMini>(packet->networkID));
|
||||
msg->clause = static_cast<MDIOMessage::Clause>(packet->header.ST);
|
||||
msg->direction = static_cast<MDIOMessage::Direction>((packet->header.OP & 0x2) ? 1 : 0);
|
||||
msg->isTXMsg = static_cast<bool>(packet->header.TRANSMIT & 0x01u);
|
||||
msg->phyAddress = (packet->header.PHY_ADDR & 0x1Fu);
|
||||
if (msg->clause == MDIOMessage::Clause::Clause45)
|
||||
{ // 16-bit register address
|
||||
msg->devAddress = (packet->header.C45_DEVTYPE & 0x1Fu);
|
||||
msg->regAddress = (packet->header.REG_ADDR & 0xFFFFu);
|
||||
}
|
||||
else
|
||||
{ // 5-bit register address
|
||||
msg->devAddress = 0;
|
||||
msg->regAddress = (packet->header.REG_ADDR & 0x1Fu);
|
||||
}
|
||||
|
||||
msg->isTXMsg = static_cast<bool>(packet->header.TRANSMIT & 0x01u);
|
||||
msg->txTimeout = static_cast<bool>(packet->header.ERR_TIMEOUT & 0x01u);
|
||||
msg->txAborted = static_cast<bool>(packet->header.ERR_JOB_CANCELLED & 0x01u);
|
||||
msg->txInvalidBus = static_cast<bool>(packet->header.ERR_INVALID_BUS & 0x01u);
|
||||
msg->txInvalidPhyAddr = static_cast<bool>(packet->header.ERR_INVALID_PHYADDR & 0x01u);
|
||||
msg->txInvalidRegAddr = static_cast<bool>(packet->header.ERR_INVALID_REGADDR & 0x01u);
|
||||
msg->txInvalidClause = static_cast<bool>(packet->header.ERR_UNSUPPORTED_CLAUSE & 0x01u);
|
||||
msg->txInvalidOpcode = static_cast<bool>(packet->header.ERR_UNSUPPORTED_OPCODE & 0x01u);
|
||||
//We don't care about 0xTRB0Dx in this case...
|
||||
//copy 0xTRB0STAT even though we likely won't use it either
|
||||
msg->description = packet->stats;
|
||||
msg->timestamp = (packet->timestamp & (0x7FFFFFFFFFFFFFFFull));
|
||||
|
||||
std::copy(packet->data, packet->data + mdioDataSize, std::back_inserter(msg->data));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
bool HardwareMDIOPacket::EncodeFromMessage(const MDIOMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& report)
|
||||
{
|
||||
const size_t numDataBytes = message.data.size();
|
||||
if(mdioDataSize < numDataBytes)
|
||||
{
|
||||
report(APIEvent::Type::MDIOMessageExceedsMaxLength, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t st = (message.clause == MDIOMessage::Clause::Clause45) ? 0x0 : 0x1;
|
||||
uint8_t op = (message.direction == MDIOMessage::Direction::Read) ? 0x2 : 0x1;
|
||||
uint8_t phyAddr = message.phyAddress & 0x1F;
|
||||
uint16_t regAddr = (message.clause == MDIOMessage::Clause::Clause45) ? message.regAddress : message.regAddress & 0x1F;
|
||||
uint8_t c45DevType = (message.clause == MDIOMessage::Clause::Clause45) ? message.devAddress & 0x1F : 0;
|
||||
|
||||
bytestream.push_back(static_cast<uint8_t>((message.description >> 8) & 0xFF)); // MSB first
|
||||
bytestream.push_back(static_cast<uint8_t>(message.description & 0xFF)); // LSB
|
||||
bytestream.push_back(op); // opcode
|
||||
bytestream.push_back(st); // st (clause)
|
||||
bytestream.push_back(phyAddr); // st (clause)
|
||||
bytestream.push_back(c45DevType); // clause 45 device type
|
||||
bytestream.push_back(regAddr & 0xFF); // reg addr LSB
|
||||
bytestream.push_back((regAddr >> 8) & 0xFF); // reg addr MSB
|
||||
|
||||
std::copy(message.data.begin(), message.data.end(), std::back_inserter(bytestream));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ option(LIBICSNEO_BUILD_CPP_INTERACTIVE_EXAMPLE "Build the command-line interacti
|
|||
option(LIBICSNEO_BUILD_CPP_A2B_EXAMPLE "Build the A2B example." ON)
|
||||
option(LIBICSNEO_BUILD_CPP_LIN_EXAMPLE "Build the LIN example." ON)
|
||||
option(LIBICSNEO_BUILD_CPP_COREMINI_EXAMPLE "Build the Coremini example." ON)
|
||||
option(LIBICSNEO_BUILD_CPP_MDIO_EXAMPLE "Build the MDIO example." ON)
|
||||
|
||||
# Disabled until we properly build these in-tree
|
||||
# option(LIBICSNEO_BUILD_CSHARP_INTERACTIVE_EXAMPLE "Build the command-line interactive C# example." OFF)
|
||||
|
|
@ -43,6 +44,10 @@ if(LIBICSNEO_BUILD_CPP_COREMINI_EXAMPLE)
|
|||
add_subdirectory(cpp/coremini)
|
||||
endif()
|
||||
|
||||
if(LIBICSNEO_BUILD_CPP_MDIO_EXAMPLE)
|
||||
add_subdirectory(cpp/mdio)
|
||||
endif()
|
||||
|
||||
# if(LIBICSNEO_BUILD_CSHARP_INTERACTIVE_EXAMPLE)
|
||||
# add_subdirectory(csharp)
|
||||
# endif()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
cmake_minimum_required(VERSION 3.2)
|
||||
project(libicsneocpp-mdio VERSION 0.1.0)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED 11)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Add an include directory like so if desired
|
||||
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
# Enable Warnings
|
||||
if(MSVC)
|
||||
# Force to always compile with W4
|
||||
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||
endif()
|
||||
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-switch -Wno-unknown-pragmas")
|
||||
endif()
|
||||
|
||||
# Add libicsneo, usually a git submodule within your project works well
|
||||
#add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../third-party/libicsneo ${CMAKE_CURRENT_BINARY_DIR}/third-party/libicsneo)
|
||||
|
||||
add_executable(libicsneocpp-mdio src/MDIOExample.cpp)
|
||||
target_link_libraries(libicsneocpp-mdio icsneocpp)
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
|
||||
#include "icsneo/icsneocpp.h"
|
||||
#include "icsneo/communication/message/mdiomessage.h"
|
||||
|
||||
/* Note: This example requires MDIO 1 channels to be connected on the device, and uses RADGalaxy or RADStar2 */
|
||||
|
||||
char getCharInput(std::vector<char> allowed)
|
||||
{
|
||||
bool found = false;
|
||||
std::string input;
|
||||
|
||||
while (!found)
|
||||
{
|
||||
std::cin >> input;
|
||||
|
||||
if (input.length() == 1)
|
||||
{
|
||||
for (char compare : allowed)
|
||||
{
|
||||
if (compare == input.c_str()[0])
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
std::cout << "Input did not match expected options. Please try again." << std::endl;
|
||||
std::cout << "<X or x to quit>" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
return input.c_str()[0];
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// Print version
|
||||
std::cout << "Running libicsneo " << icsneo::GetVersion() << std::endl;
|
||||
std::cout << "\nFinding devices... " << std::flush;
|
||||
auto devices = icsneo::FindAllDevices(); // This is type std::vector<std::shared_ptr<icsneo::Device>>
|
||||
// You now hold the shared_ptrs for these devices, you are considered to "own" these devices from a memory perspective
|
||||
std::cout << "OK, " << devices.size() << " device" << (devices.size() == 1 ? "" : "s") << " found" << std::endl;
|
||||
|
||||
// List off the devices
|
||||
for (auto &device : devices)
|
||||
std::cout << '\t' << device->describe() << " @ Handle " << device->getNeoDevice().handle << std::endl;
|
||||
std::cout << std::endl;
|
||||
|
||||
for (auto &device : devices)
|
||||
{
|
||||
std::cout << "Connecting to " << device->describe() << "... ";
|
||||
bool ret = device->open();
|
||||
if (!ret)
|
||||
{ // Failed to open
|
||||
std::cout << "FAIL" << std::endl;
|
||||
std::cout << icsneo::GetLastError() << std::endl
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
std::cout << "OK" << std::endl;
|
||||
|
||||
// The concept of going "online" tells the connected device to start listening, i.e. ACKing traffic and giving it to us
|
||||
std::cout << "\tGoing online... ";
|
||||
ret = device->goOnline();
|
||||
if (!ret)
|
||||
{
|
||||
std::cout << "FAIL" << std::endl;
|
||||
device->close();
|
||||
continue;
|
||||
}
|
||||
std::cout << "OK" << std::endl;
|
||||
|
||||
// A real application would just check the result of icsneo_goOnline() rather than calling this
|
||||
// This function is intended to be called later on if needed
|
||||
std::cout << "\tChecking online status... ";
|
||||
ret = device->isOnline();
|
||||
if (!ret)
|
||||
{
|
||||
std::cout << "FAIL\n"
|
||||
<< std::endl;
|
||||
device->close();
|
||||
continue;
|
||||
}
|
||||
std::cout << "OK" << std::endl;
|
||||
|
||||
auto handler = device->addMessageCallback(std::make_shared<icsneo::MessageCallback>([&](std::shared_ptr<icsneo::Message> message)
|
||||
{
|
||||
if(icsneo::Message::Type::Frame == message->type) {
|
||||
auto frame = std::static_pointer_cast<icsneo::Frame>(message);
|
||||
if(icsneo::Network::Type::MDIO == frame->network.getType()) {
|
||||
auto msg = std::static_pointer_cast<icsneo::MDIOMessage>(message);
|
||||
std::cout << msg->network << " " << ((msg->isTXMsg)? "TX" : "RX") << " frame\n";
|
||||
std::cout << "Clause: " << ((msg->clause == icsneo::MDIOMessage::Clause::Clause22) ? "22" : "45") << "\n";
|
||||
std::cout << "Direction: " << ((msg->direction == icsneo::MDIOMessage::Direction::Read) ? "Read" : "Write") << "\n";
|
||||
std::cout << std::hex << "PHY Address: 0x" << static_cast<int>(msg->phyAddress) << "\n";
|
||||
if(msg->clause == icsneo::MDIOMessage::Clause::Clause45)
|
||||
std::cout << std::hex << "Dev Address: 0x" << static_cast<int>(msg->devAddress) << "\n";
|
||||
std::cout << std::hex << "Reg Address: 0x" << static_cast<int>(msg->regAddress) << "\n";
|
||||
std::cout << "Data: \n";
|
||||
for(uint8_t& each : msg->data) {
|
||||
std::cout << std::hex << "0x" << static_cast<int>(each) << " ";
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
} }));
|
||||
|
||||
/*
|
||||
* BCM89810 on RADGalaxy/RADGigastar
|
||||
*/
|
||||
// We can transmit messages to read the PHY ID of BCM89810 PHY
|
||||
std::cout << "\tTransmitting a MDIO request to read ID on BCM89810...\n";
|
||||
auto mdio_r = std::make_shared<icsneo::MDIOMessage>();
|
||||
mdio_r->network = icsneo::Network::NetID::MDIO1;
|
||||
mdio_r->phyAddress = 0x00u;
|
||||
mdio_r->regAddress = 0x02u;
|
||||
mdio_r->direction = icsneo::MDIOMessage::Direction::Read;
|
||||
mdio_r->clause = icsneo::MDIOMessage::Clause::Clause22;
|
||||
ret = device->transmit(mdio_r); // This will return false if the device does not support MDIO
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
// We can transmit messages to write to arbitrary register
|
||||
std::cout << "\tTransmitting a MDIO request to write register on BCM89810...\n";
|
||||
mdio_r = std::make_shared<icsneo::MDIOMessage>();
|
||||
mdio_r->network = icsneo::Network::NetID::MDIO1;
|
||||
mdio_r->phyAddress = 0x00u;
|
||||
mdio_r->regAddress = 0x1Bu;
|
||||
mdio_r->data = {0xAA, 0xAF};
|
||||
mdio_r->direction = icsneo::MDIOMessage::Direction::Write;
|
||||
mdio_r->clause = icsneo::MDIOMessage::Clause::Clause22;
|
||||
ret = device->transmit(mdio_r); // This will return false if the device does not support MDIO
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
// We can transmit messages to read back to arbitrary register
|
||||
std::cout << "\tTransmitting a MDIO request to read register on BCM89810...\n";
|
||||
mdio_r = std::make_shared<icsneo::MDIOMessage>();
|
||||
mdio_r->network = icsneo::Network::NetID::MDIO1;
|
||||
mdio_r->phyAddress = 0x00u;
|
||||
mdio_r->regAddress = 0x1Bu;
|
||||
mdio_r->direction = icsneo::MDIOMessage::Direction::Read;
|
||||
mdio_r->clause = icsneo::MDIOMessage::Clause::Clause22;
|
||||
ret = device->transmit(mdio_r); // This will return false if the device does not support MDIO
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
/*
|
||||
* 88Q2112 on RADGigastar, RADSupermoon, RADMoon2
|
||||
*/
|
||||
// We can transmit messages to read the PHY ID of BCM89810 PHY
|
||||
std::cout << "\tTransmitting a MDIO request to read ID on 88Q2112...\n";
|
||||
mdio_r = std::make_shared<icsneo::MDIOMessage>();
|
||||
mdio_r->network = icsneo::Network::NetID::MDIO1;
|
||||
mdio_r->phyAddress = 0x06u;
|
||||
mdio_r->devAddress = 0x01u;
|
||||
mdio_r->regAddress = 0x0002u;
|
||||
mdio_r->direction = icsneo::MDIOMessage::Direction::Read;
|
||||
mdio_r->clause = icsneo::MDIOMessage::Clause::Clause45;
|
||||
ret = device->transmit(mdio_r); // This will return false if the device does not support MDIO
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
// We can transmit messages to write to arbitrary register
|
||||
std::cout << "\tTransmitting a MDIO request to write register on 88Q2112...\n";
|
||||
mdio_r = std::make_shared<icsneo::MDIOMessage>();
|
||||
mdio_r->network = icsneo::Network::NetID::MDIO1;
|
||||
mdio_r->phyAddress = 0x06u;
|
||||
mdio_r->devAddress = 0x01u;
|
||||
mdio_r->regAddress = 0x0902u;
|
||||
mdio_r->data = {0xA3, 0x02};
|
||||
mdio_r->direction = icsneo::MDIOMessage::Direction::Write;
|
||||
mdio_r->clause = icsneo::MDIOMessage::Clause::Clause45;
|
||||
ret = device->transmit(mdio_r); // This will return false if the device does not support MDIO
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
// We can transmit messages to read back to arbitrary register
|
||||
std::cout << "\tTransmitting a MDIO request to read register on 88Q2112...\n";
|
||||
mdio_r = std::make_shared<icsneo::MDIOMessage>();
|
||||
mdio_r->network = icsneo::Network::NetID::MDIO1;
|
||||
mdio_r->phyAddress = 0x06u;
|
||||
mdio_r->devAddress = 0x01u;
|
||||
mdio_r->regAddress = 0x0902u;
|
||||
mdio_r->direction = icsneo::MDIOMessage::Direction::Read;
|
||||
mdio_r->clause = icsneo::MDIOMessage::Clause::Clause45;
|
||||
ret = device->transmit(mdio_r); // This will return false if the device does not support MDIO
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
|
||||
std::cout << "<X or x to quit>\n\n";
|
||||
|
||||
// Go offline, stop sending and receiving traffic
|
||||
auto shutdown = [&]()
|
||||
{
|
||||
device->removeMessageCallback(handler);
|
||||
std::cout << "\tGoing offline... ";
|
||||
ret = device->goOffline();
|
||||
std::cout << (ret ? "OK" : "FAIL") << std::endl;
|
||||
std::cout << "\tDisconnecting... ";
|
||||
ret = device->close();
|
||||
std::cout << (ret ? "OK\n" : "FAIL\n") << std::endl;
|
||||
};
|
||||
|
||||
while (true)
|
||||
{
|
||||
char input = getCharInput(std::vector<char>{'X', 'x'});
|
||||
switch (input)
|
||||
{
|
||||
case 'X':
|
||||
case 'x':
|
||||
shutdown();
|
||||
printf("Exiting program\n");
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -111,6 +111,7 @@ public:
|
|||
ErrorSettingSocketOption = 0x3107,
|
||||
GetIfAddrsError = 0x3108,
|
||||
SendToError = 0x3109,
|
||||
MDIOMessageExceedsMaxLength = 0x3110,
|
||||
|
||||
// FTD3XX
|
||||
FTOK = 0x4000, // placeholder
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
#ifndef __MDIOMESSAGE_H_
|
||||
#define __MDIOMESSAGE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "icsneo/communication/message/message.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class MDIOMessage : public Frame {
|
||||
public:
|
||||
enum class Clause : uint8_t {
|
||||
Clause45 = 0,
|
||||
Clause22 = 1
|
||||
};
|
||||
|
||||
enum class Direction : uint8_t {
|
||||
Write = 0,
|
||||
Read = 1
|
||||
};
|
||||
|
||||
bool isTXMsg = false;
|
||||
bool txTimeout = false;
|
||||
bool txAborted = false;
|
||||
bool txInvalidBus = false;
|
||||
bool txInvalidPhyAddr = false;
|
||||
bool txInvalidRegAddr = false;
|
||||
bool txInvalidClause = false;
|
||||
bool txInvalidOpcode = false;
|
||||
uint8_t phyAddress;
|
||||
uint8_t devAddress;
|
||||
uint16_t regAddress;
|
||||
Direction direction;
|
||||
Clause clause;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
|
|
@ -91,6 +91,7 @@ public:
|
|||
Ethernet_DAQ = 69,
|
||||
Data_To_Host = 70,
|
||||
TextAPI_To_Host = 71,
|
||||
SPI1 = 72,
|
||||
OP_Ethernet6 = 73,
|
||||
Red_VBat = 74,
|
||||
OP_Ethernet7 = 75,
|
||||
|
|
@ -146,7 +147,15 @@ public:
|
|||
DWCAN16 = 541,
|
||||
LIN7 = 542,
|
||||
LIN8 = 543,
|
||||
RED_SET_RTC = 544,
|
||||
SPI2 = 544,
|
||||
MDIO1 = 545,
|
||||
MDIO2 = 546,
|
||||
MDIO3 = 547,
|
||||
MDIO4 = 548,
|
||||
MDIO5 = 549,
|
||||
MDIO6 = 550,
|
||||
MDIO7 = 551,
|
||||
MDIO8 = 552,
|
||||
Any = 0xfffe, // Never actually set as type, but used as flag for filtering
|
||||
Invalid = 0xffff
|
||||
};
|
||||
|
|
@ -163,6 +172,8 @@ public:
|
|||
ISO9141 = 9,
|
||||
I2C = 10,
|
||||
A2B = 11,
|
||||
SPI = 12,
|
||||
MDIO = 13,
|
||||
Any = 0xFE, // Never actually set as type, but used as flag for filtering
|
||||
Other = 0xFF
|
||||
};
|
||||
|
|
@ -239,6 +250,16 @@ public:
|
|||
DWCAN16 = 69,
|
||||
LIN7 = 70,
|
||||
LIN8 = 71,
|
||||
SPI1 = 72,
|
||||
SPI2 = 73,
|
||||
MDIO1 = 75,
|
||||
MDIO2 = 76,
|
||||
MDIO3 = 77,
|
||||
MDIO4 = 78,
|
||||
MDIO5 = 79,
|
||||
MDIO6 = 80,
|
||||
MDIO7 = 81,
|
||||
MDIO8 = 82,
|
||||
};
|
||||
static const char* GetTypeString(Type type) {
|
||||
switch(type) {
|
||||
|
|
@ -266,6 +287,10 @@ public:
|
|||
return "I²C";
|
||||
case Type::A2B:
|
||||
return "A2B";
|
||||
case Type::SPI:
|
||||
return "SPI";
|
||||
case Type::MDIO:
|
||||
return "MDIO";
|
||||
case Type::Invalid:
|
||||
default:
|
||||
return "Invalid Type";
|
||||
|
|
@ -327,7 +352,6 @@ public:
|
|||
case NetID::NeoMemorySDRead:
|
||||
case NetID::NeoMemoryWriteDone:
|
||||
case NetID::RED_GET_RTC:
|
||||
case NetID::RED_SET_RTC:
|
||||
return Type::Internal;
|
||||
case NetID::Invalid:
|
||||
case NetID::Any:
|
||||
|
|
@ -368,6 +392,18 @@ public:
|
|||
case NetID::A2B1:
|
||||
case NetID::A2B2:
|
||||
return Type::A2B;
|
||||
case NetID::SPI1:
|
||||
case NetID::SPI2:
|
||||
return Type::SPI;
|
||||
case NetID::MDIO1:
|
||||
case NetID::MDIO2:
|
||||
case NetID::MDIO3:
|
||||
case NetID::MDIO4:
|
||||
case NetID::MDIO5:
|
||||
case NetID::MDIO6:
|
||||
case NetID::MDIO7:
|
||||
case NetID::MDIO8:
|
||||
return Type::MDIO;
|
||||
default:
|
||||
return Type::Other;
|
||||
}
|
||||
|
|
@ -456,8 +492,6 @@ public:
|
|||
return "RED_HARDWARE_EXCEP";
|
||||
case NetID::RED_GET_RTC:
|
||||
return "RED_GET_RTC";
|
||||
case NetID::RED_SET_RTC:
|
||||
return "RED_SET_RTC";
|
||||
case NetID::ISO9141_3:
|
||||
return "ISO 9141 3";
|
||||
case NetID::HSCAN2:
|
||||
|
|
@ -626,6 +660,26 @@ public:
|
|||
return "LIN 08";
|
||||
case NetID::WBMS:
|
||||
return "WBMS";
|
||||
case NetID::SPI1:
|
||||
return "SPI 1";
|
||||
case NetID::SPI2:
|
||||
return "SPI 2";
|
||||
case NetID::MDIO1:
|
||||
return "MDIO 1";
|
||||
case NetID::MDIO2:
|
||||
return "MDIO 2";
|
||||
case NetID::MDIO3:
|
||||
return "MDIO 3";
|
||||
case NetID::MDIO4:
|
||||
return "MDIO 4";
|
||||
case NetID::MDIO5:
|
||||
return "MDIO 5";
|
||||
case NetID::MDIO6:
|
||||
return "MDIO 6";
|
||||
case NetID::MDIO7:
|
||||
return "MDIO 7";
|
||||
case NetID::MDIO8:
|
||||
return "MDIO 8";
|
||||
case NetID::Any:
|
||||
case NetID::Invalid:
|
||||
break;
|
||||
|
|
@ -778,6 +832,26 @@ public:
|
|||
return CoreMini::LIN7;
|
||||
case NetID::LIN8:
|
||||
return CoreMini::LIN8;
|
||||
case NetID::SPI1:
|
||||
return CoreMini::SPI1;
|
||||
case NetID::SPI2:
|
||||
return CoreMini::SPI2;
|
||||
case NetID::MDIO1:
|
||||
return CoreMini::MDIO1;
|
||||
case NetID::MDIO2:
|
||||
return CoreMini::MDIO2;
|
||||
case NetID::MDIO3:
|
||||
return CoreMini::MDIO3;
|
||||
case NetID::MDIO4:
|
||||
return CoreMini::MDIO4;
|
||||
case NetID::MDIO5:
|
||||
return CoreMini::MDIO5;
|
||||
case NetID::MDIO6:
|
||||
return CoreMini::MDIO6;
|
||||
case NetID::MDIO7:
|
||||
return CoreMini::MDIO7;
|
||||
case NetID::MDIO8:
|
||||
return CoreMini::MDIO8;
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
@ -928,6 +1002,27 @@ public:
|
|||
return NetID::LIN7;
|
||||
case CoreMini::LIN8:
|
||||
return NetID::LIN8;
|
||||
case CoreMini::SPI1:
|
||||
return NetID::SPI1;
|
||||
case CoreMini::SPI2:
|
||||
return NetID::SPI2;
|
||||
case CoreMini::MDIO1:
|
||||
return NetID::MDIO1;
|
||||
case CoreMini::MDIO2:
|
||||
return NetID::MDIO2;
|
||||
case CoreMini::MDIO3:
|
||||
return NetID::MDIO3;
|
||||
case CoreMini::MDIO4:
|
||||
return NetID::MDIO4;
|
||||
case CoreMini::MDIO5:
|
||||
return NetID::MDIO5;
|
||||
case CoreMini::MDIO6:
|
||||
return NetID::MDIO6;
|
||||
case CoreMini::MDIO7:
|
||||
return NetID::MDIO7;
|
||||
case CoreMini::MDIO8:
|
||||
return NetID::MDIO8;
|
||||
|
||||
}
|
||||
return NetID::Invalid; // Should be unreachable, the compiler should warn about new CoreMini IDs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef __MDIOPACKET_H__
|
||||
#define __MDIOPACKET_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "icsneo/communication/message/mdiomessage.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include "icsneo/communication/packetizer.h"
|
||||
#include "icsneo/communication/network.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
#pragma pack(push, 2)
|
||||
|
||||
struct HardwareMDIOPacket {
|
||||
|
||||
static std::shared_ptr<Message> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||
static bool EncodeFromMessage(const MDIOMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& report);
|
||||
|
||||
struct {
|
||||
// C1xMDIO
|
||||
uint16_t PHY_ADDR : 5; // mdio phy address, 5-bit
|
||||
uint16_t ST : 2; // Start of Frame (Clause 22/45)
|
||||
uint16_t OP : 2; // OP Code (Read/Write)
|
||||
uint16_t ADVANCED_MODE : 1; // future?
|
||||
uint16_t TRANSMIT : 1; // This is a TX message
|
||||
uint16_t C45_DEVTYPE : 5;
|
||||
|
||||
// C2xMDIO
|
||||
uint16_t ERR_JOB_CANCELLED : 1; // error flag
|
||||
uint16_t ERR_TIMEOUT : 1; // error flag
|
||||
uint16_t ERR_INVALID_BUS : 1; // error flag
|
||||
uint16_t ERR_INVALID_PHYADDR : 1; // error flag
|
||||
uint16_t ERR_INVALID_REGADDR : 1; // error flag
|
||||
uint16_t ERR_UNSUPPORTED_CLAUSE : 1; // error flag
|
||||
uint16_t ERR_UNSUPPORTED_OPCODE : 1; // error flag
|
||||
uint16_t ERR_OVERFLOW : 1; // error flag
|
||||
uint16_t : 8;
|
||||
|
||||
// C3xMDIO
|
||||
uint16_t REG_ADDR;
|
||||
} header;
|
||||
|
||||
uint8_t data[8];
|
||||
uint16_t stats;
|
||||
uint64_t timestamp;
|
||||
uint16_t networkID;
|
||||
uint16_t length;
|
||||
|
||||
static const size_t mdioDataSize;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
}
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
|
|
@ -32,7 +32,9 @@ public:
|
|||
Network::NetID::A2B2,
|
||||
|
||||
Network::NetID::I2C,
|
||||
Network::NetID::I2C2
|
||||
Network::NetID::I2C2,
|
||||
|
||||
Network::NetID::MDIO1,
|
||||
};
|
||||
return supportedNetworks;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,13 @@ public:
|
|||
Network::NetID::OP_Ethernet9,
|
||||
Network::NetID::OP_Ethernet10,
|
||||
Network::NetID::OP_Ethernet11,
|
||||
Network::NetID::OP_Ethernet12
|
||||
Network::NetID::OP_Ethernet12,
|
||||
|
||||
Network::NetID::MDIO1,
|
||||
Network::NetID::MDIO2,
|
||||
Network::NetID::MDIO3,
|
||||
Network::NetID::MDIO4,
|
||||
Network::NetID::MDIO5,
|
||||
};
|
||||
return supportedNetworks;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,9 @@ protected:
|
|||
Network::NetID::I2C,
|
||||
Network::NetID::I2C2,
|
||||
Network::NetID::I2C3,
|
||||
|
||||
Network::NetID::MDIO1,
|
||||
Network::NetID::MDIO2,
|
||||
};
|
||||
rxNetworks.insert(rxNetworks.end(), supportedRxNetworks.begin(), supportedRxNetworks.end());
|
||||
}
|
||||
|
|
@ -91,6 +94,9 @@ protected:
|
|||
Network::NetID::I2C,
|
||||
Network::NetID::I2C2,
|
||||
Network::NetID::I2C3,
|
||||
|
||||
Network::NetID::MDIO1,
|
||||
Network::NetID::MDIO2,
|
||||
};
|
||||
txNetworks.insert(txNetworks.end(), supportedTxNetworks.begin(), supportedTxNetworks.end());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ protected:
|
|||
Network::NetID::FlexRay1b,
|
||||
|
||||
Network::NetID::I2C,
|
||||
|
||||
Network::NetID::MDIO1,
|
||||
Network::NetID::MDIO2,
|
||||
};
|
||||
rxNetworks.insert(rxNetworks.end(), supportedRxNetworks.begin(), supportedRxNetworks.end());
|
||||
}
|
||||
|
|
@ -84,6 +87,9 @@ protected:
|
|||
// FlexRay is Receive Only
|
||||
|
||||
Network::NetID::I2C,
|
||||
|
||||
Network::NetID::MDIO1,
|
||||
Network::NetID::MDIO2,
|
||||
};
|
||||
txNetworks.insert(txNetworks.end(), supportedTxNetworks.begin(), supportedTxNetworks.end());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,14 @@ public:
|
|||
APM1000E_CLK, // Clock Option and Keysight Branding
|
||||
};
|
||||
|
||||
static const std::vector<Network>& GetSupportedNetworks() {
|
||||
static std::vector<Network> supportedNetworks = {
|
||||
Network::NetID::MDIO1,
|
||||
Network::NetID::MDIO2,
|
||||
};
|
||||
return supportedNetworks;
|
||||
}
|
||||
|
||||
SKU getSKU() const {
|
||||
switch(getSerial().back()) {
|
||||
case 'A':
|
||||
|
|
@ -66,6 +74,14 @@ protected:
|
|||
|
||||
bool requiresVehiclePower() const override { return false; }
|
||||
|
||||
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
|
||||
for(auto& netid : GetSupportedNetworks())
|
||||
rxNetworks.emplace_back(netid);
|
||||
}
|
||||
|
||||
// The supported TX networks are the same as the supported RX networks for this device
|
||||
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
|
||||
|
||||
std::optional<MemoryAddress> getCoreminiStartAddressFlash() const override {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,10 @@ public:
|
|||
Network::NetID::Ethernet,
|
||||
|
||||
Network::NetID::OP_Ethernet1,
|
||||
Network::NetID::OP_Ethernet2
|
||||
Network::NetID::OP_Ethernet2,
|
||||
|
||||
Network::NetID::MDIO1,
|
||||
Network::NetID::MDIO2,
|
||||
};
|
||||
return supportedNetworks;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ public:
|
|||
static std::vector<Network> supportedNetworks = {
|
||||
Network::NetID::Ethernet,
|
||||
Network::NetID::OP_Ethernet1,
|
||||
Network::NetID::MDIO1,
|
||||
Network::NetID::MDIO2,
|
||||
};
|
||||
return supportedNetworks;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "icsneo/communication/message/i2cmessage.h"
|
||||
#include "icsneo/communication/message/a2bmessage.h"
|
||||
#include "icsneo/communication/message/linmessage.h"
|
||||
#include "icsneo/communication/message/mdiomessage.h"
|
||||
|
||||
#include "icsneo/communication/message/callback/streamoutput/a2bwavoutput.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,227 @@
|
|||
#include "icsneo/icsneocpp.h"
|
||||
#include "icsneo/communication/encoder.h"
|
||||
#include "icsneo/communication/packet/mdiopacket.h"
|
||||
#include "icsneo/communication/message/mdiomessage.h"
|
||||
#include "icsneo/communication/packetizer.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <vector>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
class MDIOEncoderDecoderTest : 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);
|
||||
});
|
||||
}
|
||||
device_eventhandler_t report;
|
||||
std::optional<Encoder> packetEncoder;
|
||||
std::optional<Packetizer> packetizer;
|
||||
std::optional<Decoder> packetDecoder;
|
||||
|
||||
std::vector<uint8_t> testBytesClause22 =
|
||||
{0xAA, 0x0C, 0x11, 0x00, 0x21, 0x02, 0xAB, 0xCD,
|
||||
0x01, 0x01, 0x18, 0x00, 0x14, 0x00, 0x56, 0x78};
|
||||
|
||||
std::vector<uint8_t> testBytesClause45 =
|
||||
{0xAA, 0x0C, 0x11, 0x00, 0x21, 0x02, 0xAB, 0xCD,
|
||||
0x02, 0x00, 0x06, 0x14, 0x34, 0x12, 0x56, 0x78};
|
||||
|
||||
std::vector<uint8_t> testBytesClause22Mask =
|
||||
{0xAA, 0x0C, 0x11, 0x00, 0x21, 0x02, 0xFF, 0xFF,
|
||||
0x01, 0x01, 0x1F, 0x00, 0x1F, 0x00, 0xFF, 0xFF};
|
||||
|
||||
std::vector<uint8_t> testBytesClause45Mask =
|
||||
{0xAA, 0x0C, 0x11, 0x00, 0x21, 0x02, 0xFF, 0xFF,
|
||||
0x02, 0x00, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
std::vector<uint8_t> recvBytesClause22 =
|
||||
{
|
||||
0xaa, 0x0c, // header
|
||||
0x22, 0x00, // length
|
||||
0x21, 0x02, // hw netid
|
||||
0x26, 0x0D, // word1
|
||||
0x00, 0x00, // word2
|
||||
0x14, 0x00, // word3
|
||||
0x56, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // data[8]
|
||||
0xCD, 0xAB, // stats
|
||||
0x97, 0x29, 0xe6, 0xfb, 0xc1, 0xfc, 0xb0, 0x80, // timestamp
|
||||
0x4A, 0x00, // netid
|
||||
0x00, 0x00, // length
|
||||
};
|
||||
std::vector<uint8_t> recvBytesClause45 =
|
||||
{
|
||||
0xaa, 0x0c, // header
|
||||
0x22, 0x00, // length
|
||||
0x21, 0x02, // hw netid
|
||||
0x92, 0x1C, // word1
|
||||
0xFF, 0x00, // word2
|
||||
0x56, 0x14, // word3
|
||||
0x56, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // data[8]
|
||||
0xCD, 0xAB, // stats
|
||||
0x97, 0x29, 0xe6, 0xfb, 0xc1, 0xfc, 0xb0, 0x80, // timestamp
|
||||
0x4A, 0x00, // netid
|
||||
0x00, 0x00, // length
|
||||
};
|
||||
};
|
||||
|
||||
TEST_F(MDIOEncoderDecoderTest, PacketEncoderClause22Test) {
|
||||
std::vector<uint8_t> bytestream;
|
||||
auto message = std::make_shared<icsneo::MDIOMessage>();
|
||||
message->network = icsneo::Network::NetID::MDIO1;
|
||||
message->description = 0xABCD;
|
||||
message->phyAddress = 0x18u;
|
||||
message->devAddress = 0x13u;
|
||||
message->regAddress = 0x14u;
|
||||
message->data = {0x56u, 0x78u};
|
||||
message->direction = MDIOMessage::Direction::Write;
|
||||
message->clause = MDIOMessage::Clause::Clause22;
|
||||
message->isTXMsg = true;
|
||||
packetEncoder->encode(*packetizer, bytestream, message);
|
||||
EXPECT_EQ(bytestream, testBytesClause22);
|
||||
}
|
||||
|
||||
TEST_F(MDIOEncoderDecoderTest, PacketEncoderClause45Test) {
|
||||
std::vector<uint8_t> bytestream;
|
||||
auto message = std::make_shared<icsneo::MDIOMessage>();
|
||||
message->network = icsneo::Network::NetID::MDIO1;
|
||||
message->description = 0xABCD;
|
||||
message->phyAddress = 0x06u;
|
||||
message->devAddress = 0x14u;
|
||||
message->regAddress = 0x1234u;
|
||||
message->data = {0x56u, 0x78u};
|
||||
message->direction = MDIOMessage::Direction::Read;
|
||||
message->clause = MDIOMessage::Clause::Clause45;
|
||||
message->isTXMsg = true;
|
||||
packetEncoder->encode(*packetizer, bytestream, message);
|
||||
EXPECT_EQ(bytestream, testBytesClause45);
|
||||
}
|
||||
|
||||
TEST_F(MDIOEncoderDecoderTest, PacketEncoderClause22MaskTest) {
|
||||
std::vector<uint8_t> bytestream;
|
||||
auto message = std::make_shared<icsneo::MDIOMessage>();
|
||||
message->network = icsneo::Network::NetID::MDIO1;
|
||||
message->description = 0xFFFFu;
|
||||
message->phyAddress = 0xFFu;
|
||||
message->devAddress = 0xFFu;
|
||||
message->regAddress = 0xFFFFu;
|
||||
message->data = {0xFFu, 0xFFu};
|
||||
message->direction = MDIOMessage::Direction::Write;
|
||||
message->clause = MDIOMessage::Clause::Clause22;
|
||||
message->isTXMsg = true;
|
||||
packetEncoder->encode(*packetizer, bytestream, message);
|
||||
EXPECT_EQ(bytestream, testBytesClause22Mask);
|
||||
}
|
||||
|
||||
TEST_F(MDIOEncoderDecoderTest, PacketEncoderClause45MaskTest) {
|
||||
std::vector<uint8_t> bytestream;
|
||||
auto message = std::make_shared<icsneo::MDIOMessage>();
|
||||
message->network = icsneo::Network::NetID::MDIO1;
|
||||
message->description = 0xFFFFu;
|
||||
message->phyAddress = 0xFFu;
|
||||
message->devAddress = 0xFFu;
|
||||
message->regAddress = 0xFFFFu;
|
||||
message->data = {0xFFu, 0xFFu};
|
||||
message->direction = MDIOMessage::Direction::Read;
|
||||
message->clause = MDIOMessage::Clause::Clause45;
|
||||
message->isTXMsg = true;
|
||||
packetEncoder->encode(*packetizer, bytestream, message);
|
||||
EXPECT_EQ(bytestream, testBytesClause45Mask);
|
||||
}
|
||||
|
||||
TEST_F(MDIOEncoderDecoderTest, PacketDecoderClause22Test) {
|
||||
std::shared_ptr<icsneo::Message> decodeMsg;
|
||||
std::shared_ptr<icsneo::MDIOMessage> message = std::make_shared<icsneo::MDIOMessage>();
|
||||
|
||||
message->network = icsneo::Network::NetID::MDIO1;
|
||||
message->description = 0xABCD;
|
||||
message->phyAddress = 0x06u;
|
||||
message->devAddress = 0x00u;
|
||||
message->regAddress = 0x14u;
|
||||
message->data = {0x56u, 0x78u};
|
||||
message->direction = MDIOMessage::Direction::Read;
|
||||
message->clause = MDIOMessage::Clause::Clause22;
|
||||
message->isTXMsg = true;
|
||||
message->timestamp = static_cast<uint64_t>(0xB0FCC1FBE62997);
|
||||
|
||||
EXPECT_TRUE(packetizer->input(recvBytesClause22));
|
||||
auto packets = packetizer->output();
|
||||
EXPECT_FALSE(packets.empty());
|
||||
EXPECT_TRUE(packetDecoder->decode(decodeMsg, packets.back()));
|
||||
auto testMessage = std::dynamic_pointer_cast<icsneo::MDIOMessage>(decodeMsg);
|
||||
EXPECT_EQ(message->network, testMessage->network);
|
||||
EXPECT_EQ(message->description, testMessage->description);
|
||||
EXPECT_EQ(message->phyAddress, testMessage->phyAddress);
|
||||
EXPECT_EQ(message->devAddress, testMessage->devAddress);
|
||||
EXPECT_EQ(message->regAddress, testMessage->regAddress);
|
||||
EXPECT_EQ(message->data, testMessage->data);
|
||||
EXPECT_EQ(message->direction, testMessage->direction);
|
||||
EXPECT_EQ(message->clause, testMessage->clause);
|
||||
EXPECT_EQ(message->isTXMsg, testMessage->isTXMsg);
|
||||
EXPECT_EQ(message->txTimeout, testMessage->txTimeout);
|
||||
EXPECT_EQ(message->txAborted, testMessage->txAborted);
|
||||
EXPECT_EQ(message->txInvalidBus, testMessage->txInvalidBus);
|
||||
EXPECT_EQ(message->txInvalidPhyAddr, testMessage->txInvalidPhyAddr);
|
||||
EXPECT_EQ(message->txInvalidRegAddr, testMessage->txInvalidRegAddr);
|
||||
EXPECT_EQ(message->txInvalidClause, testMessage->txInvalidClause);
|
||||
EXPECT_EQ(message->txInvalidOpcode, testMessage->txInvalidOpcode);
|
||||
EXPECT_EQ(message->timestamp, testMessage->timestamp);
|
||||
}
|
||||
|
||||
TEST_F(MDIOEncoderDecoderTest, PacketDecoderClause45Test) {
|
||||
std::shared_ptr<icsneo::Message> decodeMsg;
|
||||
std::shared_ptr<icsneo::MDIOMessage> message = std::make_shared<icsneo::MDIOMessage>();
|
||||
|
||||
message->network = icsneo::Network::NetID::MDIO1;
|
||||
message->description = 0xABCD;
|
||||
message->phyAddress = 0x12u;
|
||||
message->devAddress = 0x03u;
|
||||
message->regAddress = 0x1456u;
|
||||
message->data = {0x56u, 0x78u};
|
||||
message->direction = MDIOMessage::Direction::Write;
|
||||
message->clause = MDIOMessage::Clause::Clause45;
|
||||
message->isTXMsg = true;
|
||||
message->txTimeout = true;
|
||||
message->txAborted = true;
|
||||
message->txInvalidBus = true;
|
||||
message->txInvalidPhyAddr = true;
|
||||
message->txInvalidRegAddr = true;
|
||||
message->txInvalidClause = true;
|
||||
message->txInvalidOpcode = true;
|
||||
message->timestamp = static_cast<uint64_t>(0xB0FCC1FBE62997);
|
||||
|
||||
EXPECT_TRUE(packetizer->input(recvBytesClause45));
|
||||
auto packets = packetizer->output();
|
||||
EXPECT_FALSE(packets.empty());
|
||||
EXPECT_TRUE(packetDecoder->decode(decodeMsg, packets.back()));
|
||||
auto testMessage = std::dynamic_pointer_cast<icsneo::MDIOMessage>(decodeMsg);
|
||||
EXPECT_EQ(message->network, testMessage->network);
|
||||
EXPECT_EQ(message->description, testMessage->description);
|
||||
EXPECT_EQ(message->phyAddress, testMessage->phyAddress);
|
||||
EXPECT_EQ(message->devAddress, testMessage->devAddress);
|
||||
EXPECT_EQ(message->regAddress, testMessage->regAddress);
|
||||
EXPECT_EQ(message->data, testMessage->data);
|
||||
EXPECT_EQ(message->direction, testMessage->direction);
|
||||
EXPECT_EQ(message->clause, testMessage->clause);
|
||||
EXPECT_EQ(message->isTXMsg, testMessage->isTXMsg);
|
||||
EXPECT_EQ(message->txTimeout, testMessage->txTimeout);
|
||||
EXPECT_EQ(message->txAborted, testMessage->txAborted);
|
||||
EXPECT_EQ(message->txInvalidBus, testMessage->txInvalidBus);
|
||||
EXPECT_EQ(message->txInvalidPhyAddr, testMessage->txInvalidPhyAddr);
|
||||
EXPECT_EQ(message->txInvalidRegAddr, testMessage->txInvalidRegAddr);
|
||||
EXPECT_EQ(message->txInvalidClause, testMessage->txInvalidClause);
|
||||
EXPECT_EQ(message->txInvalidOpcode, testMessage->txInvalidOpcode);
|
||||
EXPECT_EQ(message->timestamp, testMessage->timestamp);
|
||||
}
|
||||
Loading…
Reference in New Issue