Communication: Add SPI support
parent
6d82289864
commit
88d32128c9
|
|
@ -204,6 +204,7 @@ set(SRC_FILES
|
||||||
communication/packet/flexraypacket.cpp
|
communication/packet/flexraypacket.cpp
|
||||||
communication/packet/canpacket.cpp
|
communication/packet/canpacket.cpp
|
||||||
communication/packet/a2bpacket.cpp
|
communication/packet/a2bpacket.cpp
|
||||||
|
communication/packet/spipacket.cpp
|
||||||
communication/packet/ethernetpacket.cpp
|
communication/packet/ethernetpacket.cpp
|
||||||
communication/packet/versionpacket.cpp
|
communication/packet/versionpacket.cpp
|
||||||
communication/packet/iso9141packet.cpp
|
communication/packet/iso9141packet.cpp
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ pybind11_add_module(icsneopy
|
||||||
icsneopy/communication/message/mdiomessage.cpp
|
icsneopy/communication/message/mdiomessage.cpp
|
||||||
icsneopy/communication/message/gptpstatusmessage.cpp
|
icsneopy/communication/message/gptpstatusmessage.cpp
|
||||||
icsneopy/communication/message/ethernetstatusmessage.cpp
|
icsneopy/communication/message/ethernetstatusmessage.cpp
|
||||||
|
icsneopy/communication/message/spimessage.cpp
|
||||||
icsneopy/communication/message/macsecmessage.cpp
|
icsneopy/communication/message/macsecmessage.cpp
|
||||||
icsneopy/communication/message/scriptstatusmessage.cpp
|
icsneopy/communication/message/scriptstatusmessage.cpp
|
||||||
icsneopy/communication/message/callback/messagecallback.cpp
|
icsneopy/communication/message/callback/messagecallback.cpp
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
#include <pybind11/stl.h>
|
||||||
|
#include <pybind11/functional.h>
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/spimessage.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
void init_spimessage(pybind11::module_& m) {
|
||||||
|
pybind11::class_<SPIMessage, std::shared_ptr<SPIMessage>, Frame> spiMessage(m, "SPIMessage");
|
||||||
|
pybind11::enum_<SPIMessage::Direction>(spiMessage, "Direction")
|
||||||
|
.value("Write", SPIMessage::Direction::Write)
|
||||||
|
.value("Read", SPIMessage::Direction::Read);
|
||||||
|
spiMessage
|
||||||
|
.def(pybind11::init())
|
||||||
|
.def_readwrite("direction", &SPIMessage::direction)
|
||||||
|
.def_readwrite("address", &SPIMessage::address)
|
||||||
|
.def_readwrite("mms", &SPIMessage::mms)
|
||||||
|
.def_readwrite("stats", &SPIMessage::stats)
|
||||||
|
.def_readwrite("payload", &SPIMessage::payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace icsneo
|
||||||
|
|
||||||
|
|
@ -20,6 +20,7 @@ void init_linmessage(pybind11::module_&);
|
||||||
void init_tc10statusmessage(pybind11::module_&);
|
void init_tc10statusmessage(pybind11::module_&);
|
||||||
void init_gptpstatusmessage(pybind11::module_&);
|
void init_gptpstatusmessage(pybind11::module_&);
|
||||||
void init_mdiomessage(pybind11::module_&);
|
void init_mdiomessage(pybind11::module_&);
|
||||||
|
void init_spimessage(pybind11::module_&);
|
||||||
void init_ethernetstatusmessage(pybind11::module_&);
|
void init_ethernetstatusmessage(pybind11::module_&);
|
||||||
void init_macsecmessage(pybind11::module_&);
|
void init_macsecmessage(pybind11::module_&);
|
||||||
void init_scriptstatusmessage(pybind11::module_&);
|
void init_scriptstatusmessage(pybind11::module_&);
|
||||||
|
|
@ -55,6 +56,7 @@ PYBIND11_MODULE(icsneopy, m) {
|
||||||
init_ethernetstatusmessage(m);
|
init_ethernetstatusmessage(m);
|
||||||
init_macsecmessage(m);
|
init_macsecmessage(m);
|
||||||
init_scriptstatusmessage(m);
|
init_scriptstatusmessage(m);
|
||||||
|
init_spimessage(m);
|
||||||
init_messagefilter(m);
|
init_messagefilter(m);
|
||||||
init_messagecallback(m);
|
init_messagecallback(m);
|
||||||
init_diskdriver(m);
|
init_diskdriver(m);
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@
|
||||||
#include "icsneo/communication/packet/genericbinarystatuspacket.h"
|
#include "icsneo/communication/packet/genericbinarystatuspacket.h"
|
||||||
#include "icsneo/communication/packet/livedatapacket.h"
|
#include "icsneo/communication/packet/livedatapacket.h"
|
||||||
#include "icsneo/communication/packet/hardwareinfopacket.h"
|
#include "icsneo/communication/packet/hardwareinfopacket.h"
|
||||||
|
#include "icsneo/communication/packet/spipacket.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
@ -184,6 +185,19 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||||
msg.timestamp *= timestampResolution;
|
msg.timestamp *= timestampResolution;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case Network::Type::SPI: {
|
||||||
|
result = HardwareSPIPacket::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
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIMessage& msg = *static_cast<SPIMessage*>(result.get());
|
||||||
|
msg.network = packet->network;
|
||||||
|
msg.timestamp *= timestampResolution;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
case Network::Type::MDIO: {
|
case Network::Type::MDIO: {
|
||||||
result = HardwareMDIOPacket::DecodeToMessage(packet->data);
|
result = HardwareMDIOPacket::DecodeToMessage(packet->data);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include "icsneo/communication/packet/a2bpacket.h"
|
#include "icsneo/communication/packet/a2bpacket.h"
|
||||||
#include "icsneo/communication/packet/linpacket.h"
|
#include "icsneo/communication/packet/linpacket.h"
|
||||||
#include "icsneo/communication/packet/mdiopacket.h"
|
#include "icsneo/communication/packet/mdiopacket.h"
|
||||||
|
#include "icsneo/communication/packet/spipacket.h"
|
||||||
|
|
||||||
using namespace icsneo;
|
using namespace icsneo;
|
||||||
|
|
||||||
|
|
@ -133,6 +134,17 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} // End of Network::Type::MDIO
|
} // End of Network::Type::MDIO
|
||||||
|
case Network::Type::SPI: {
|
||||||
|
auto msg = std::dynamic_pointer_cast<SPIMessage>(message);
|
||||||
|
if(!msg) {
|
||||||
|
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||||
|
return false; // The message was not a properly formed LiveDataMessage
|
||||||
|
}
|
||||||
|
if(!HardwareSPIPacket::EncodeFromMessage(*msg, result, report))
|
||||||
|
return false;
|
||||||
|
result = packetizer.packetWrap(result, false);
|
||||||
|
return true;
|
||||||
|
} // End of Network::Type::SPI
|
||||||
default:
|
default:
|
||||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
#include "icsneo/communication/packet/spipacket.h"
|
||||||
|
#include "icsneo/communication/command.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace icsneo;
|
||||||
|
|
||||||
|
static size_t SPISubHeaderLength = 5u;
|
||||||
|
|
||||||
|
std::shared_ptr<Message> HardwareSPIPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||||
|
if(bytestream.size() < sizeof(HardwareSPIPacket)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
const HardwareSPIPacket* packet = (const HardwareSPIPacket*)bytestream.data();
|
||||||
|
size_t totalPackedLength = static_cast<size_t>(bytestream.size()) - sizeof(HardwareSPIPacket); // First 28 bytes are message header.
|
||||||
|
if(totalPackedLength < SPISubHeaderLength) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* bytes = bytestream.data() + sizeof(HardwareSPIPacket);
|
||||||
|
std::shared_ptr<SPIMessage> msg = std::make_shared<SPIMessage>();
|
||||||
|
msg->direction = static_cast<SPIMessage::Direction>(bytes[0]);
|
||||||
|
msg->address = *reinterpret_cast<const uint16_t*>(&bytes[1]);
|
||||||
|
msg->mms = bytes[3];
|
||||||
|
msg->stats = packet->stats;
|
||||||
|
msg->timestamp = packet->timestamp.TS;
|
||||||
|
|
||||||
|
size_t numWords = (totalPackedLength - SPISubHeaderLength) / 4;
|
||||||
|
msg->payload.reserve(numWords);
|
||||||
|
for(size_t offset = SPISubHeaderLength; offset < totalPackedLength; offset += 4) {
|
||||||
|
msg->payload.push_back(*reinterpret_cast<const uint32_t*>(bytes + offset));
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HardwareSPIPacket::EncodeFromMessage(const SPIMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& /*report*/) {
|
||||||
|
// Payload length is everything excluding cmdHeader (note at the beginning there is an offset of 2)
|
||||||
|
uint16_t payloadLength = static_cast<uint16_t>(
|
||||||
|
2 +
|
||||||
|
sizeof(HardwareSPIPacket) +
|
||||||
|
SPISubHeaderLength +
|
||||||
|
message.payload.size() * sizeof(uint32_t)
|
||||||
|
);
|
||||||
|
if(payloadLength % 2) {
|
||||||
|
// Pad payload to even number
|
||||||
|
payloadLength++;
|
||||||
|
}
|
||||||
|
// +1 for AA, another +1 for firmware nuance
|
||||||
|
uint16_t fullSize = 1 + sizeof(ExtendedCommandHeader) + payloadLength + 1;
|
||||||
|
uint16_t unwrappedSize = sizeof(ExtendedCommandHeader) + payloadLength; // fullSize without AA and firmware nuance
|
||||||
|
|
||||||
|
bytestream.resize(unwrappedSize, 0);
|
||||||
|
uint32_t offset = 0;
|
||||||
|
auto* cmdHeader = reinterpret_cast<ExtendedCommandHeader*>(bytestream.data() + offset);
|
||||||
|
cmdHeader->netid = static_cast<uint8_t>(Network::NetID::Main51);
|
||||||
|
cmdHeader->fullLength = fullSize;
|
||||||
|
cmdHeader->command = static_cast<uint8_t>(Command::Extended);
|
||||||
|
cmdHeader->extendedCommand = static_cast<uint16_t>(ExtendedCommand::TransmitCoreminiMessage);
|
||||||
|
cmdHeader->payloadLength = payloadLength;
|
||||||
|
|
||||||
|
offset += sizeof(ExtendedCommandHeader) + 2; // Offset of 2 between header and packet
|
||||||
|
auto* packet = reinterpret_cast<HardwareSPIPacket*>(bytestream.data() + offset);
|
||||||
|
packet->header.frameLength = static_cast<uint16_t>(SPISubHeaderLength + message.payload.size() * sizeof(uint32_t));
|
||||||
|
packet->networkID = static_cast<uint16_t>(message.network.getNetID());
|
||||||
|
packet->length = packet->header.frameLength;
|
||||||
|
packet->timestamp.IsExtended = 1;
|
||||||
|
|
||||||
|
offset += sizeof(HardwareSPIPacket);
|
||||||
|
// Write the sub header details
|
||||||
|
bytestream[offset++] = static_cast<uint8_t>(message.direction);
|
||||||
|
bytestream[offset++] = static_cast<uint8_t>(message.address & 0xFF);
|
||||||
|
bytestream[offset++] = static_cast<uint8_t>((message.address >> 8) & 0xFF);
|
||||||
|
bytestream[offset++] = static_cast<uint8_t>(message.mms);
|
||||||
|
bytestream[offset++] = static_cast<uint8_t>(message.payload.size());
|
||||||
|
|
||||||
|
// Write the words
|
||||||
|
for(uint32_t word : message.payload) {
|
||||||
|
*reinterpret_cast<uint32_t*>(bytestream.data() + offset) = word;
|
||||||
|
offset += sizeof(uint32_t);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ option(LIBICSNEO_BUILD_CPP_MDIO_EXAMPLE "Build the MDIO example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_VSA_EXAMPLE "Build the VSA example." ON)
|
option(LIBICSNEO_BUILD_CPP_VSA_EXAMPLE "Build the VSA example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_APP_ERROR_EXAMPLE "Build the app error example." ON)
|
option(LIBICSNEO_BUILD_CPP_APP_ERROR_EXAMPLE "Build the app error example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_FLEXRAY_EXAMPLE "Build the FlexRay example." ON)
|
option(LIBICSNEO_BUILD_CPP_FLEXRAY_EXAMPLE "Build the FlexRay example." ON)
|
||||||
|
option(LIBICSNEO_BUILD_CPP_SPI_EXAMPLE "Build the SPI example." ON)
|
||||||
|
|
||||||
if(LIBICSNEO_BUILD_C_INTERACTIVE_EXAMPLE)
|
if(LIBICSNEO_BUILD_C_INTERACTIVE_EXAMPLE)
|
||||||
add_subdirectory(c/interactive)
|
add_subdirectory(c/interactive)
|
||||||
|
|
@ -63,3 +64,7 @@ endif()
|
||||||
if(LIBICSNEO_BUILD_CPP_FLEXRAY_EXAMPLE)
|
if(LIBICSNEO_BUILD_CPP_FLEXRAY_EXAMPLE)
|
||||||
add_subdirectory(cpp/flexray)
|
add_subdirectory(cpp/flexray)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(LIBICSNEO_BUILD_CPP_SPI_EXAMPLE)
|
||||||
|
add_subdirectory(cpp/spi)
|
||||||
|
endif()
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
add_executable(libicsneocpp-spi src/spi.cpp)
|
||||||
|
target_link_libraries(libicsneocpp-spi icsneocpp)
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
/**
|
||||||
|
* libicsneo SPI message example
|
||||||
|
*
|
||||||
|
* Read a register on NetID::SPI_01 and display the result to stdout
|
||||||
|
*
|
||||||
|
* Usage: libicsneo-spi [deviceSerial] [address] [numWords]
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* deviceSerial: 6 character string for device serial
|
||||||
|
* address: 16 bit register address
|
||||||
|
* numWords: number of words to read
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
#include <string_view>
|
||||||
|
#include <utility>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "icsneo/icsneocpp.h"
|
||||||
|
#include "icsneo/communication/message/spimessage.h"
|
||||||
|
|
||||||
|
static const std::string usage = "Usage: libicsneo-spi [deviceSerial] [address] [numWords]\n\n"
|
||||||
|
"Arguments:\n"
|
||||||
|
"deviceSerial: 6 character string for device serial\n"
|
||||||
|
"address: hex number representing 16 bit register number\n"
|
||||||
|
"numWords: number of words to read\n";
|
||||||
|
|
||||||
|
static std::tuple<std::string_view, uint16_t, uint16_t> parseArgs(std::vector<std::string_view>& args, bool& fail) {
|
||||||
|
|
||||||
|
if(args.size() != 4) {
|
||||||
|
std::cerr << "Invalid argument count" << std::endl;
|
||||||
|
std::cerr << usage;
|
||||||
|
fail = true;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string_view serial = args[1];
|
||||||
|
if(serial.size() != 6) {
|
||||||
|
std::cerr << "Invalid serial length" << std::endl;
|
||||||
|
std::cerr << usage;
|
||||||
|
fail = true;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
char* endPtr;
|
||||||
|
uint16_t address = static_cast<uint16_t>(std::strtoul(args[2].data(), &endPtr, 16));
|
||||||
|
if(endPtr != (args[2].data() + args[2].size())) {
|
||||||
|
std::cerr << "Failed to convert address to hex" << std::endl;
|
||||||
|
std::cerr << usage;
|
||||||
|
fail = true;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t numWords = static_cast<uint16_t>(std::strtoul(args[3].data(), &endPtr, 16));
|
||||||
|
if(endPtr != (args[3].data() + args[3].size())) {
|
||||||
|
std::cerr << "Failed to convert numWords to decimal integer" << std::endl;
|
||||||
|
std::cerr << usage;
|
||||||
|
fail = true;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
fail = false;
|
||||||
|
return {serial, address, numWords};
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char** argv) {
|
||||||
|
std::vector<std::string_view> args(argv, argv + argc);
|
||||||
|
bool fail;
|
||||||
|
auto tup = parseArgs(args, fail);
|
||||||
|
if(fail) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auto serial = std::get<0>(tup);
|
||||||
|
auto address = std::get<1>(tup);
|
||||||
|
auto numWords = std::get<2>(tup);
|
||||||
|
|
||||||
|
std::shared_ptr<icsneo::Device> device = nullptr;
|
||||||
|
for(const auto& dev : icsneo::FindAllDevices()) {
|
||||||
|
if(dev->getSerial() == serial) {
|
||||||
|
device = dev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!device) {
|
||||||
|
std::cerr << "Failed to find device" << std::endl;
|
||||||
|
std::cerr << usage;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(!device->open()) {
|
||||||
|
std::cerr << "Failed to open device" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(!device->goOnline()) {
|
||||||
|
std::cerr << "Failed to go online" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Reading register " << std::setfill('0') << std::setw(4) << std::right << std::hex << address << std::endl;
|
||||||
|
|
||||||
|
// Make message
|
||||||
|
std::shared_ptr<icsneo::SPIMessage> msg = std::make_shared<icsneo::SPIMessage>();
|
||||||
|
msg->network = icsneo::Network::NetID::SPI_01;
|
||||||
|
msg->direction = icsneo::SPIMessage::Direction::Read;
|
||||||
|
msg->address = address;
|
||||||
|
msg->payload.resize(numWords, 0); // Resize payload to desired length
|
||||||
|
|
||||||
|
// Add callback
|
||||||
|
bool receivedMessage = false;
|
||||||
|
auto handle = device->addMessageCallback(std::make_shared<icsneo::MessageCallback>([&](std::shared_ptr<icsneo::Message> msg) {
|
||||||
|
if(receivedMessage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(msg->type == icsneo::Message::Type::Frame) {
|
||||||
|
auto frame = std::dynamic_pointer_cast<icsneo::Frame>(msg);
|
||||||
|
if(!frame) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(frame->network == icsneo::Network::NetID::SPI_01) {
|
||||||
|
auto spiMsg = std::dynamic_pointer_cast<icsneo::SPIMessage>(frame);
|
||||||
|
if(spiMsg->address == address) {
|
||||||
|
std::cout << "Received " << spiMsg->payload.size() << " words" << std::endl;
|
||||||
|
for(uint32_t word : spiMsg->payload) {
|
||||||
|
std::cout << std::setfill('0') << std::setw(8) << std::right << std::hex << word << ' ';
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
receivedMessage = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
device->transmit(msg);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
|
||||||
|
|
||||||
|
if(!receivedMessage) {
|
||||||
|
std::cout << "Did not receive response from device." << std::endl;
|
||||||
|
}
|
||||||
|
device->removeMessageCallback(handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -56,6 +56,7 @@ enum class ExtendedCommand : uint16_t {
|
||||||
GetComponentVersions = 0x001A,
|
GetComponentVersions = 0x001A,
|
||||||
Reboot = 0x001C,
|
Reboot = 0x001C,
|
||||||
SetRootFSEntryFlags = 0x0027,
|
SetRootFSEntryFlags = 0x0027,
|
||||||
|
TransmitCoreminiMessage = 0x0028,
|
||||||
GenericBinaryInfo = 0x0030,
|
GenericBinaryInfo = 0x0030,
|
||||||
LiveData = 0x0035,
|
LiveData = 0x0035,
|
||||||
RequestTC10Wake = 0x003D,
|
RequestTC10Wake = 0x003D,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef __SPIMESSAGE_H_
|
||||||
|
#define __SPIMESSAGE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/communication/message/message.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
class SPIMessage : public Frame {
|
||||||
|
public:
|
||||||
|
enum class Direction : uint8_t {
|
||||||
|
Read = 0,
|
||||||
|
Write = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
Direction direction = Direction::Read;
|
||||||
|
uint16_t address = static_cast<uint16_t>(0x0000u);
|
||||||
|
uint8_t mms = static_cast<uint16_t>(0x0000u); // Memory Map Selector for ADI MAC Phy
|
||||||
|
uint16_t stats = static_cast<uint16_t>(0x0000u);
|
||||||
|
|
||||||
|
std::vector<uint32_t> payload;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef __SPIPACKET_H__
|
||||||
|
#define __SPIPACKET_H__
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
#include "icsneo/api/eventmanager.h"
|
||||||
|
#include <cstdint>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include "icsneo/communication/message/spimessage.h"
|
||||||
|
|
||||||
|
namespace icsneo {
|
||||||
|
|
||||||
|
typedef uint16_t icscm_bitfield;
|
||||||
|
|
||||||
|
#pragma pack(push, 2)
|
||||||
|
struct HardwareSPIPacket {
|
||||||
|
|
||||||
|
static std::shared_ptr<Message> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||||
|
static bool EncodeFromMessage(const SPIMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& report);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint16_t frameLength;
|
||||||
|
} header;
|
||||||
|
uint8_t offset[12];
|
||||||
|
uint16_t stats;
|
||||||
|
struct {
|
||||||
|
uint64_t TS : 60;
|
||||||
|
uint64_t : 3; // Reserved for future status bits
|
||||||
|
uint64_t IsExtended : 1;
|
||||||
|
} timestamp;
|
||||||
|
uint16_t networkID;
|
||||||
|
uint16_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Reference in New Issue