diff --git a/api/icsneoc/icsneoc.cpp b/api/icsneoc/icsneoc.cpp index 93ac522..29eb4e6 100644 --- a/api/icsneoc/icsneoc.cpp +++ b/api/icsneoc/icsneoc.cpp @@ -597,4 +597,20 @@ bool icsneo_getSupportedDevices(devicetype_t* devices, size_t* count) { *count = len; return true; -} \ No newline at end of file +} + +extern bool DLLExport icsneo_getTimestampResolution(const neodevice_t* device, uint16_t* resolution) +{ + if (!icsneo_isValidNeoDevice(device)) { + ErrorManager::GetInstance().add(APIError::InvalidNeoDevice); + return false; + } + + if (resolution == nullptr) { + ErrorManager::GetInstance().add(APIError::RequiredParameterNull); + return false; + } + + *resolution = device->device->getTimestampResolution(); + return true; +} diff --git a/api/icsneolegacy/icsneolegacy.cpp b/api/icsneolegacy/icsneolegacy.cpp index 7e9e1b3..59ec2d0 100644 --- a/api/icsneolegacy/icsneolegacy.cpp +++ b/api/icsneolegacy/icsneolegacy.cpp @@ -37,7 +37,7 @@ static NeoDevice OldNeoDeviceFromNew(const neodevice_t* newnd) { return oldnd; } -static void NeoMessageToSpyMessage(const neomessage_t& newmsg, icsSpyMessage& oldmsg) { +static void NeoMessageToSpyMessage(const neodevice_t* device, const neomessage_t& newmsg, icsSpyMessage& oldmsg) { memset(&oldmsg, 0, sizeof(icsSpyMessage)); oldmsg.NumberBytesData = (uint8_t)std::min(newmsg.length, (size_t)255); oldmsg.NumberBytesHeader = 4; @@ -59,6 +59,25 @@ static void NeoMessageToSpyMessage(const neomessage_t& newmsg, icsSpyMessage& ol oldmsg.Protocol = SPY_PROTOCOL_ETHERNET; break; } + + // Timestamp - epoch = 1/1/2007 - 25ns per tick most of the time + uint64_t t = newmsg.timestamp; + uint16_t res = 0; + if (icsneo_getTimestampResolution(device, &res)) { + t /= res; + oldmsg.TimeHardware2 = (unsigned long)(t >> 32); + oldmsg.TimeHardware = (unsigned long)(t & 0xFFFFFFFF); + switch (res) { + case 25: + oldmsg.TimeStampHardwareID = HARDWARE_TIMESTAMP_ID_NEORED_25NS; + break; + case 10: + oldmsg.TimeStampHardwareID = HARDWARE_TIMESTAMP_ID_NEORED_10NS; + break; + default: + oldmsg.TimeStampHardwareID = HARDWARE_TIMESTAMP_ID_NONE; + } + } } //Basic Functions @@ -180,7 +199,7 @@ int icsneoGetMessages(void* hObject, icsSpyMessage* pMsg, int* pNumberOfMessages *pNumberOfErrors = 0; for(size_t i = 0; i < messageCount; i++) - NeoMessageToSpyMessage(messages[i], pMsg[i]); + NeoMessageToSpyMessage(device, messages[i], pMsg[i]); return true; } @@ -226,8 +245,26 @@ int icsneoEnableNetworkRXQueue(void* hObject, int iEnable) { } int icsneoGetTimeStampForMsg(void* hObject, icsSpyMessage* pMsg, double* pTimeStamp) { - // TODO Implement - return false; + if(!icsneoValidateHObject(hObject)) + return false; + neodevice_t* device = (neodevice_t*)hObject; + + uint16_t resolution = 0; + if (!icsneo_getTimestampResolution(device, &resolution)) + return false; + + // Convert back to ticks + uint64_t ticks = pMsg->TimeHardware2; + ticks <<= 32; + ticks += pMsg->TimeHardware; + + // convert to ns + ticks *= resolution; + + // icsneoGetTimeStampForMsg() expects pTimeStamp to be in seconds + *pTimeStamp = ticks / (double)1000000000; + + return true; } void icsneoGetISO15765Status(void* hObject, int lNetwork, int lClearTxStatus, int lClearRxStatus, int*lTxStatus, int*lRxStatus) { diff --git a/communication/decoder.cpp b/communication/decoder.cpp index 863d2fa..3bb8edd 100644 --- a/communication/decoder.cpp +++ b/communication/decoder.cpp @@ -25,9 +25,9 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrtimestamp *= timestampMultiplier; + // Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000 + // The resolution depends on the device + result->timestamp *= timestampResolution; result->network = packet->network; return true; case Network::Type::CAN: @@ -40,9 +40,9 @@ bool Decoder::decode(std::shared_ptr& result, const std::shared_ptrtimestamp *= timestampMultiplier; + // Timestamps are in (resolution) ns increments since 1/1/2007 GMT 00:00:00.0000 + // The resolution depends on the device + result->timestamp *= timestampResolution; result->network = packet->network; return true; } diff --git a/communication/packet/canpacket.cpp b/communication/packet/canpacket.cpp index 2bb57c8..9ec41b6 100644 --- a/communication/packet/canpacket.cpp +++ b/communication/packet/canpacket.cpp @@ -17,8 +17,8 @@ std::shared_ptr HardwareCANPacket::DecodeToMessage(const std::vector msg->arbid = data->header.SID; } - // This timestamp is raw off the device (in timestampMultiplier increments) - // Decoder will fix as it has information about the timestampMultiplier increments + // This timestamp is raw off the device (in timestampResolution increments) + // Decoder will fix as it has information about the timestampResolution increments msg->timestamp = data->timestamp.TS; // DLC diff --git a/communication/packet/ethernetpacket.cpp b/communication/packet/ethernetpacket.cpp index e380f9f..4d1f6bd 100644 --- a/communication/packet/ethernetpacket.cpp +++ b/communication/packet/ethernetpacket.cpp @@ -40,8 +40,8 @@ std::shared_ptr HardwareEthernetPacket::DecodeToMessage(const s if(message.frameTooShort) message.error = true; - // This timestamp is raw off the device (in timestampMultiplier increments) - // Decoder will fix as it has information about the timestampMultiplier increments + // This timestamp is raw off the device (in timestampResolution increments) + // Decoder will fix as it has information about the timestampResolution increments message.timestamp = packet->timestamp.TS; // Network ID is also not set, this will be fixed in the Decoder as well diff --git a/device/device.cpp b/device/device.cpp index 04ec6e8..741286e 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -67,6 +67,10 @@ bool Device::SerialStringIsNumeric(const std::string& serial) { return isdigit(serial[0]) && isdigit(serial[1]); } +uint16_t Device::getTimestampResolution() const { + return com->decoder->timestampResolution; +} + std::string Device::describe() const { std::stringstream ss; ss << getType() << ' ' << getSerial(); diff --git a/include/icsneo/communication/decoder.h b/include/icsneo/communication/decoder.h index 792cd37..bdeab9d 100644 --- a/include/icsneo/communication/decoder.h +++ b/include/icsneo/communication/decoder.h @@ -19,7 +19,7 @@ public: Decoder(device_errorhandler_t err) : err(err) {} bool decode(std::shared_ptr& result, const std::shared_ptr& packet); - int timestampMultiplier = 25; + uint16_t timestampResolution = 25; private: device_errorhandler_t err; diff --git a/include/icsneo/device/device.h b/include/icsneo/device/device.h index 5a1a252..410d391 100644 --- a/include/icsneo/device/device.h +++ b/include/icsneo/device/device.h @@ -29,6 +29,7 @@ public: static uint32_t SerialStringToNum(const std::string& serial); static bool SerialStringIsNumeric(const std::string& serial); + uint16_t getTimestampResolution() const; DeviceType getType() const { return DeviceType(data.type); } uint16_t getProductId() const { return productId; } std::string getSerial() const { return data.serial; } diff --git a/include/icsneo/device/radgalaxy/radgalaxy.h b/include/icsneo/device/radgalaxy/radgalaxy.h index 43ec2d8..9b8319b 100644 --- a/include/icsneo/device/radgalaxy/radgalaxy.h +++ b/include/icsneo/device/radgalaxy/radgalaxy.h @@ -99,7 +99,7 @@ protected: virtual void setupDecoder(Decoder& decoder) override { Device::setupDecoder(decoder); - decoder.timestampMultiplier = 10; // Timestamps are in 10ns increments instead of the usual 25ns + decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns } virtual void setupSupportedRXNetworks(std::vector& rxNetworks) override { diff --git a/include/icsneo/device/radstar2/radstar2.h b/include/icsneo/device/radstar2/radstar2.h index dea0e17..19450bf 100644 --- a/include/icsneo/device/radstar2/radstar2.h +++ b/include/icsneo/device/radstar2/radstar2.h @@ -41,7 +41,7 @@ protected: virtual void setupDecoder(Decoder& decoder) override { Device::setupDecoder(decoder); - decoder.timestampMultiplier = 10; // Timestamps are in 10ns increments instead of the usual 25ns + decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns } virtual void setupSupportedRXNetworks(std::vector& rxNetworks) override { diff --git a/include/icsneo/device/radsupermoon/radsupermoon.h b/include/icsneo/device/radsupermoon/radsupermoon.h index 22cdfd5..75af958 100644 --- a/include/icsneo/device/radsupermoon/radsupermoon.h +++ b/include/icsneo/device/radsupermoon/radsupermoon.h @@ -23,7 +23,7 @@ public: protected: virtual void setupDecoder(Decoder& decoder) override { - decoder.timestampMultiplier = 10; // Timestamps are in 10ns increments instead of the usual 25ns + decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns } private: diff --git a/include/icsneo/icsnVC40.h b/include/icsneo/icsnVC40.h index ce89fe1..6548e78 100644 --- a/include/icsneo/icsnVC40.h +++ b/include/icsneo/icsnVC40.h @@ -398,6 +398,18 @@ typedef unsigned __int64 uint64_t; #define NEOVI_RED_TIMESTAMP_2_10NS 429.4967296 #define NEOVI_RED_TIMESTAMP_1_10NS 0.000000010 +#define HARDWARE_TIMESTAMP_ID_NONE (unsigned char)0 +#define HARDWARE_TIMESTAMP_ID_VSI (unsigned char)1 +#define HARDWARE_TIMESTAMP_ID_AVT_716 (unsigned char)2 +#define HARDWARE_TIMESTAMP_ID_NI_CAN (unsigned char)3 +#define HARDWARE_TIMESTAMP_ID_NEOVI (unsigned char)4 +#define HARDWARE_TIMESTAMP_ID_AVT_717 (unsigned char)5 +#define HARDWARE_TIMESTAMP_ID_NEOv6_VCAN (unsigned char)6 +#define HARDWARE_TIMESTAMP_ID_DOUBLE_SEC (unsigned char)7 +#define HARDWARE_TIMESTAMP_ID_NEORED_10US (unsigned char)8 +#define HARDWARE_TIMESTAMP_ID_NEORED_25NS (unsigned char)9 +#define HARDWARE_TIMESTAMP_ID_NEORED_10NS (unsigned char)10 + typedef struct { uint32_t DeviceType; diff --git a/include/icsneo/icsneoc.h b/include/icsneo/icsneoc.h index 3a5e7f2..4d9cd1b 100644 --- a/include/icsneo/icsneoc.h +++ b/include/icsneo/icsneoc.h @@ -626,6 +626,18 @@ extern size_t DLLExport icsneo_getErrorLimit(void); */ extern bool DLLExport icsneo_getSupportedDevices(devicetype_t* devices, size_t* count); +/** + * \brief Get the timestamp resolution for the given device + * \param[out] device A pointer to the neodevice_t structure specifying the device to read out the timestamp for. + * \param[out] resolution A pointer to a uint16_t where the resolution will be stored. This value is in nanoseconds. + + * \returns True if the resolution was written + */ +extern bool DLLExport icsneo_getTimestampResolution(const neodevice_t* device, uint16_t* resolution); + + + + #ifdef __cplusplus } // extern "C" #endif