mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 01:18:36 +02:00
I2C: Network support
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "icsneo/communication/message/scriptstatusmessage.h"
|
||||
#include "icsneo/communication/message/a2bmessage.h"
|
||||
#include "icsneo/communication/message/flexray/control/flexraycontrolmessage.h"
|
||||
#include "icsneo/communication/message/i2cmessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/communication/packet/canpacket.h"
|
||||
@@ -21,6 +22,7 @@
|
||||
#include "icsneo/communication/packet/ethphyregpacket.h"
|
||||
#include "icsneo/communication/packet/logicaldiskinfopacket.h"
|
||||
#include "icsneo/communication/packet/wivicommandpacket.h"
|
||||
#include "icsneo/communication/packet/i2cpacket.h"
|
||||
#include "icsneo/communication/packet/scriptstatuspacket.h"
|
||||
#include <iostream>
|
||||
|
||||
@@ -122,6 +124,20 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
iso.network = packet->network;
|
||||
return true;
|
||||
}
|
||||
case Network::Type::I2C: {
|
||||
if(packet->data.size() < sizeof(HardwareI2CPacket)) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
result = HardwareI2CPacket::DecodeToMessage(packet->data);
|
||||
if(!result) {
|
||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||
return false; //malformed packet indicated by a nullptr return
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
case Network::Type::Internal: {
|
||||
switch(packet->network.getNetID()) {
|
||||
case Network::NetID::Reset_Status: {
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "icsneo/communication/packet/canpacket.h"
|
||||
#include "icsneo/communication/packet/ethphyregpacket.h"
|
||||
#include "icsneo/communication/message/ethphymessage.h"
|
||||
#include "icsneo/communication/packet/i2cpacket.h"
|
||||
#include "icsneo/communication/message/i2cmessage.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
@@ -68,6 +70,18 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
||||
// packets to the device. This function just encodes them back to back into `result`
|
||||
return HardwareISO9141Packet::EncodeFromMessage(*isomsg, result, report, packetizer);
|
||||
} // End of Network::Type::ISO9141
|
||||
case Network::Type::I2C: {
|
||||
auto i2cmsg = std::dynamic_pointer_cast<I2CMessage>(message);
|
||||
if(!i2cmsg) {
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
buffer = &result;
|
||||
if(!HardwareI2CPacket::EncodeFromMessage(*i2cmsg, result, report)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#include "icsneo/communication/packet/i2cpacket.h"
|
||||
|
||||
namespace icsneo
|
||||
{
|
||||
std::shared_ptr<Message> HardwareI2CPacket::DecodeToMessage(const std::vector<uint8_t>& bytestream)
|
||||
{
|
||||
auto msg = std::make_shared<I2CMessage>();
|
||||
const I2CHeader* packet = reinterpret_cast<const I2CHeader*>(bytestream.data());
|
||||
const size_t numPayloadBytes = packet->length;
|
||||
const size_t numControlBytes = packet->CoreMiniBitsI2C.CBLen;
|
||||
const size_t numDataBytes = numPayloadBytes - numControlBytes;
|
||||
if( (numPayloadBytes == 0) || (numDataBytes > I2CMaxLength) ||
|
||||
(sizeof(I2CHeader) != (bytestream.size() - numPayloadBytes)) )
|
||||
{ return nullptr; }
|
||||
|
||||
msg->network = Network::GetNetIDFromCoreMiniNetwork(static_cast<Network::CoreMini>(packet->networkID));
|
||||
msg->address = (packet->CoreMiniBitsI2C.ID & 0x3FFu);
|
||||
msg->deviceMode = static_cast<I2CMessage::DeviceMode>(packet->CoreMiniBitsI2C.CT);
|
||||
msg->direction = static_cast<I2CMessage::Direction>(packet->CoreMiniBitsI2C.DIR);
|
||||
|
||||
msg->isExtendedID = static_cast<bool>(packet->CoreMiniBitsI2C.EID & 0x01u);
|
||||
msg->isTXMsg = static_cast<bool>(packet->CoreMiniBitsI2C.TXMsg & 0x01u);
|
||||
msg->txTimeout = static_cast<bool>(packet->CoreMiniBitsI2C.TXTimeout & 0x01u);
|
||||
msg->txNack = static_cast<bool>(packet->CoreMiniBitsI2C.TXNack & 0x01u);
|
||||
msg->txAborted = static_cast<bool>(packet->CoreMiniBitsI2C.TXAborted & 0x01u);
|
||||
msg->txLostArb = static_cast<bool>(packet->CoreMiniBitsI2C.TXLostArb & 0x01u);
|
||||
msg->txError = static_cast<bool>(packet->CoreMiniBitsI2C.TXError & 0x01u);
|
||||
//We don't care about 0xTRB0Dx in this case...
|
||||
//copy 0xTRB0STAT even though we likely won't use it either
|
||||
msg->stats = packet->stats;
|
||||
msg->timestamp = (packet->timestamp & (0x7FFFFFFFFFFFFFFFull));
|
||||
|
||||
//The device will combine the 'control' bytes and data bytes into one payload
|
||||
//The control bytes will always come before the data
|
||||
auto cbStart = bytestream.begin() + sizeof(I2CHeader);
|
||||
auto dataStart = cbStart + numControlBytes;
|
||||
std::copy(cbStart, dataStart, std::back_inserter(msg->controlBytes));
|
||||
std::copy(dataStart, bytestream.end(), std::back_inserter(msg->dataBytes));
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
bool HardwareI2CPacket::EncodeFromMessage(const I2CMessage& message, std::vector<uint8_t>& bytestream, const device_eventhandler_t& report)
|
||||
{
|
||||
const size_t numControlBytes = message.controlBytes.size();
|
||||
const size_t numDataBytes = message.dataBytes.size();
|
||||
if(I2CMaxLength < numDataBytes)
|
||||
{
|
||||
report(APIEvent::Type::I2CMessageExceedsMaxLength, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
if(message.controlBytes.empty() || message.dataBytes.empty())
|
||||
{
|
||||
//You'll need to provide a target R/W register in controlBytes
|
||||
//alternatively, you're expecting to read without providing a dataBytes payload
|
||||
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
bytestream.push_back(static_cast<uint8_t>(numControlBytes & 0xFFu));
|
||||
bytestream.push_back(static_cast<uint8_t>((numControlBytes) >> 8) & 0xFFu);
|
||||
bytestream.push_back(static_cast<uint8_t>(numDataBytes & 0xFFu));
|
||||
bytestream.push_back(static_cast<uint8_t>((numDataBytes) >> 8) & 0xFFu);
|
||||
bytestream.push_back(static_cast<uint8_t>((message.stats) >> 8) & 0xFFu);
|
||||
bytestream.push_back(static_cast<uint8_t>(message.stats & 0xFFu));
|
||||
|
||||
if(message.isExtendedID)
|
||||
{
|
||||
bytestream.push_back(static_cast<uint8_t>(message.address & 0xFFu));
|
||||
bytestream.push_back(static_cast<uint8_t>(((message.address) >> 8) & 0x03u) | 0x04u);
|
||||
} else {
|
||||
bytestream.push_back(static_cast<uint8_t>(message.address & 0xFFu));
|
||||
bytestream.push_back(static_cast<uint8_t>(0x00u));
|
||||
}
|
||||
|
||||
if(I2CMessage::Direction::Read == message.direction)
|
||||
{ bytestream.back() |= static_cast<uint8_t>(0x10u); }
|
||||
|
||||
std::copy(message.controlBytes.begin(), message.controlBytes.end(), std::back_inserter(bytestream));
|
||||
std::copy(message.dataBytes.begin(), message.dataBytes.end(), std::back_inserter(bytestream));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user