commit f3d130e4ad0650f02a9b3f3b7225dd745d92b2fa Author: cfif Date: Mon Jun 2 13:26:41 2025 +0300 Init diff --git a/Inc/EcallTypes.h b/Inc/EcallTypes.h new file mode 100644 index 0000000..07e55f6 --- /dev/null +++ b/Inc/EcallTypes.h @@ -0,0 +1,24 @@ +// +// Created by xemon on 8/23/22. +// + +#ifndef MODULE_ECALLTYPES_H +#define MODULE_ECALLTYPES_H + +typedef enum { + AUTOMATIC_ACTIVATION = 1, + MANUAL_ACTIVATION = 0 +} eEcallActivationType; + +typedef enum { + TEST_CALL = 1, + EMERGENCY_CALL = 0 +} eEcallTestMode; + +typedef enum { + NOT_CHANGE_TIME = 2, + GNSS_TIME_SOURSE = 1, + RTC_TIME_SOURSE = 0 +} eEcallTimeSourse; + +#endif //MODULE_ECALLTYPES_H diff --git a/Inc/EraGlonassMsd.h b/Inc/EraGlonassMsd.h new file mode 100644 index 0000000..5188f01 --- /dev/null +++ b/Inc/EraGlonassMsd.h @@ -0,0 +1,177 @@ +/* + * msd.h + * + * Created on: Oct 20, 2020 + * Author: FICOM-IT LTD + */ + +#ifndef INC_MSD_H_ +#define INC_MSD_H_ + +#include +#include +#include +#include "EcallTypes.h" + + +#define ERA_GLONASS_MSD_ENCODED_BUFFER_LENGTH 128 + + +typedef enum { + MSD_V_1 = 1, + MSD_V_2 = 2, +} eEraGlonassMsd_Version; + + +// @brief Control and status data +typedef struct { + uint16_t extraData; // 000 - additional data excluded, 010 - additional data included + uint16_t recentPos1; // True if previous location is available + uint16_t recentPos2; // True if previous location is available + uint16_t passengers; // True if passangers' number is available + uint16_t activation; // True if Automatic, False if manual eCall activation + uint16_t testCall; // True if test eCall, Flase if not test eCall + uint16_t posStatus; // True if GPS position can be trusted + uint16_t vehicleType; // Vehicle identification according to 2007/46/EC, 2002/24/EC + uint16_t includedTanks; // if True include status data (present/not present) for the relevant tank +} tEraGlonassMsd_Control; + +// @brief Vehicle location stored in milli-arc-second +typedef struct { + int32_t lat; // Position latitude + int32_t lon; // Position longitude +} tEraGlonassMsd_GpsPos; + +// @brief Vehicle location difference with the previous location stored in milli-arc-second +typedef struct { + uint16_t lat; + uint16_t lon; +} tEraGlonassMsd_PosDelta; + +typedef enum { + ERA_GLONASS_MSD_OPTIONAL_FLAG_ABSENT = 0, + ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_TRUE = 1, + ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_FALSE = 2, +} tEraGlonassMsd_OptionalFlagState; + +typedef uint8_t tEraGlonassMsd_OptionalFlag; + +#define EraGlonassMsd_OptionalFlagClear(FLAG) (GLAG) = ERA_GLONASS_MSD_OPTIONAL_FLAG_ABSENT +#define EraGlonassMsd_OptionalFlagSet(FLAG, VALUE) (FLAG) = (VALUE) ? ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_TRUE : ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_FALSE + +typedef struct { + tEraGlonassMsd_OptionalFlag CrashFront; + tEraGlonassMsd_OptionalFlag CrashLeftSide; + tEraGlonassMsd_OptionalFlag CrashRightSide; + tEraGlonassMsd_OptionalFlag CrashRear; + tEraGlonassMsd_OptionalFlag CrashWithRollover; + tEraGlonassMsd_OptionalFlag CrashSide; + tEraGlonassMsd_OptionalFlag CrashFrontOrSide; + tEraGlonassMsd_OptionalFlag CrashOtherType; +} tMSD_CrashInfo; + +#define EraGlonassMsd_CrashInfoClear(ENV) memset(ENV, 0, sizeof(tMSD_CrashInfo)) + +typedef struct { + tEraGlonassMsd_OptionalFlag micConnectionFailure; + tEraGlonassMsd_OptionalFlag micFailure; + tEraGlonassMsd_OptionalFlag rightSpeakerFailure; + tEraGlonassMsd_OptionalFlag leftSpeakerFailure; + tEraGlonassMsd_OptionalFlag speakersFailure; + tEraGlonassMsd_OptionalFlag ignitionLineFailure; + tEraGlonassMsd_OptionalFlag uimFailure; + tEraGlonassMsd_OptionalFlag statusIndicatorFailure; + tEraGlonassMsd_OptionalFlag batteryFailure; + tEraGlonassMsd_OptionalFlag batteryVoltageLow; + tEraGlonassMsd_OptionalFlag crashSensorFailure; + tEraGlonassMsd_OptionalFlag firmwareImageCorruption; + tEraGlonassMsd_OptionalFlag commModuleInterfaceFailure; + tEraGlonassMsd_OptionalFlag gnssReceiverFailure; + tEraGlonassMsd_OptionalFlag raimProblem; + tEraGlonassMsd_OptionalFlag gnssAntennaFailure; + tEraGlonassMsd_OptionalFlag commModuleFailure; + tEraGlonassMsd_OptionalFlag eventsMemoryOverflow; + tEraGlonassMsd_OptionalFlag crashProfileMemoryOverflow; + tEraGlonassMsd_OptionalFlag otherCriticalFailures; + tEraGlonassMsd_OptionalFlag otherNotCriticalFailures; +} tMSD_DiagnosticResult; + +typedef enum { + ERA_GLONASS_MSD_COORDINATE_SYSTEM_TYPE_WGS84 = 0x01, + ERA_GLONASS_MSD_COORDINATE_SYSTEM_TYPE_PZ90 = 0x02, +} eEraGlonassMsd_CoordinateSystemType; + +typedef struct { + bool asi15Present; + bool crashInfoPresent; + + uint16_t asi15; + tMSD_CrashInfo crashInfo; + eEraGlonassMsd_CoordinateSystemType coordSystem; + tMSD_DiagnosticResult *diagnosticResult; +} tEraGlonassMsd_AdditionalData; + + +// @brief MSD data structure +typedef struct { + uint16_t msdId; // MSD format version set to 1 + uint16_t msgId; // Message identifier, starting with 1 for each new eCall session + tEraGlonassMsd_Control MSD_Control; // Control flags and data + uint16_t vin[18]; // VIN + uint16_t propulsion; // Vehicle propulsion storage type + uint32_t timestamp; // Timestamp + tEraGlonassMsd_GpsPos pos; // Vehicle position + uint8_t direction; // Vehicle heading, course over ground, course over north + tEraGlonassMsd_PosDelta MSD_PosDelta[2]; // Previous position delta + + bool additionalDataPresent; + tEraGlonassMsd_AdditionalData additionalData; // Additional data +} tEraGlonassMsd_DataTypedef; + + +typedef struct { + tEraGlonassMsd_DataTypedef MSD_Data; +// tEraGlonassMsd_GpsPos lastPos; +} tEraGlonassMsd; + + +//Must be called on create +void EraGlonassMsdInit(tEraGlonassMsd *env); + +void EraGlonassMsd_ClearDiagnostic(tMSD_DiagnosticResult *env); + +//Must be called when settings changed +void EraGlonassMsdSetPassengersNumber(tEraGlonassMsd *env, uint16_t value); + +void EraGlonassMsdSetVehicleType(tEraGlonassMsd *env, eUveosGostVehicleType value); + +void EraGlonassMsdSetVIN(tEraGlonassMsd *env, char *vin, uint8_t vinLen); + +void EraGlonassMsdSetPropulsionStorageType(tEraGlonassMsd *env, eUveosGostVehiclePropulsionStorageType value); + +//Must be called when gnss data changed +void EraGlonassMsdSetTimeStamp(tEraGlonassMsd *env, uint32_t timestamp); + +void EraGlonassMsdSetPositionValue( + tEraGlonassMsd *env, + int32_t lonArc, + int32_t latArc, + uint16_t track, + uint8_t valid +); + +void EraGlonassMsdNoGnssSetDefaults(tEraGlonassMsd *env); + + +//Called on emergency situation +void EraGlonassMsdSetDataEmergencySituationFlags( + tEraGlonassMsd *env, + int MSD_MSG_ID, + eEcallActivationType eCallType, + eEcallTestMode eCallTestMode +); + +uint16_t EraGlonassMsdEncode(tEraGlonassMsd *env, eEraGlonassMsd_Version msdVersion, uint8_t *encoded); + + +#endif /* INC_MSD_H_ */ diff --git a/Src/EraGlonassMsd.c b/Src/EraGlonassMsd.c new file mode 100644 index 0000000..902cc00 --- /dev/null +++ b/Src/EraGlonassMsd.c @@ -0,0 +1,529 @@ +/* + * msd.c + * + * Created on: OCT 21, 2020 + * Author: FICOM-IT LTD + */ + +#include "EraGlonassMsd.h" +#include "BitBuffer.h" +#include + + +void EraGlonassMsdInit(tEraGlonassMsd *env) { + +// env->lastPos = (tEraGlonassMsd_GpsPos) {512, 512}; + + //init not changeable fields + env->MSD_Data.msgId = 0; + + env->MSD_Data.msdId = MSD_V_2; // MSD format version + + env->MSD_Data.MSD_Control.extraData = 0x00; // Additional information not included + + // aGpsStatus + env->MSD_Data.MSD_Control.recentPos1 = 0x01; // Recent vehicle position 1 available + env->MSD_Data.MSD_Control.recentPos2 = 0x01; // Recent vehicle position 2 available + + env->MSD_Data.additionalData.coordSystem = ERA_GLONASS_MSD_COORDINATE_SYSTEM_TYPE_WGS84; + env->MSD_Data.additionalData.diagnosticResult = NULL; +} + +void EraGlonassMsd_ClearDiagnostic(tMSD_DiagnosticResult *env) { + memset(env, 0, sizeof(tMSD_DiagnosticResult)); +} + +// In case we don't have valid GPS data set defaults as described in EN15722 +void EraGlonassMsdNoGnssSetDefaults(tEraGlonassMsd *env) { + env->MSD_Data.timestamp = 0x00; + env->MSD_Data.pos.lat = 0xFFFFFFFF; + env->MSD_Data.pos.lon = 0xFFFFFFFF; + + env->MSD_Data.direction = 0xFF; + + env->MSD_Data.MSD_PosDelta[0].lat = 512; + env->MSD_Data.MSD_PosDelta[0].lon = 512; + + env->MSD_Data.MSD_PosDelta[1].lat = 512; + env->MSD_Data.MSD_PosDelta[1].lon = 512; + + // aGpsStatus + env->MSD_Data.MSD_Control.recentPos1 = 0x00; // Recent vehicle position 1 available + env->MSD_Data.MSD_Control.recentPos2 = 0x00; // Recent vehicle position 2 available +} + +void EraGlonassMsdSetDataEmergencySituationFlags( + tEraGlonassMsd *env, + int MSD_MSG_ID, + eEcallActivationType eCallType, + eEcallTestMode eCallTestMode +) { + // Message ID + env->MSD_Data.msgId = MSD_MSG_ID; + + // Automatic or manual eCall activation + if (eCallType == AUTOMATIC_ACTIVATION) { + env->MSD_Data.MSD_Control.activation = 1; + } + if (eCallType == MANUAL_ACTIVATION) { + env->MSD_Data.MSD_Control.activation = 0; + } + + // Test eCall + if (eCallTestMode == TEST_CALL) { + env->MSD_Data.MSD_Control.testCall = 1; + } + if (eCallTestMode == EMERGENCY_CALL) { + env->MSD_Data.MSD_Control.testCall = 0; + } + +} + +void EraGlonassMsdCalcPosDelta(tEraGlonassMsd *env, tEraGlonassMsd_GpsPos lastPos) { + int16_t deltaLat = 0, deltaLon = 0; + + deltaLat = (lastPos.lat - env->MSD_Data.pos.lat) / 100; + deltaLon = (lastPos.lon - env->MSD_Data.pos.lon) / 100; + + if (deltaLat <= -512) { + deltaLat = -512; + } else if (deltaLat >= 511) { + deltaLat = 511; + } + deltaLat += 512; // Make offset + + if (deltaLon <= -512) { + deltaLon = -512; + } else if (deltaLon >= 511) { + deltaLon = 511; + } + deltaLon += 512; + + + env->MSD_Data.MSD_PosDelta[1].lat = env->MSD_Data.MSD_PosDelta[0].lat; + env->MSD_Data.MSD_PosDelta[1].lon = env->MSD_Data.MSD_PosDelta[0].lon; + env->MSD_Data.MSD_Control.recentPos2 = env->MSD_Data.MSD_Control.recentPos1; + + env->MSD_Data.MSD_PosDelta[0].lat = deltaLat; + env->MSD_Data.MSD_PosDelta[0].lon = deltaLon; + env->MSD_Data.MSD_Control.recentPos1 = 0x01; + + //Update to the latest position in order to calculate + //correctly the deltas on the next iteration +// env->lastPos.lat = env->MSD_Data.pos.lat; +// env->lastPos.lon = env->MSD_Data.pos.lon; +} + +void EraGlonassMsdSetTimeStamp(tEraGlonassMsd *env, uint32_t timestamp) { + env->MSD_Data.timestamp = timestamp; +} + +void EraGlonassMsdSetPositionValue( + tEraGlonassMsd *env, + int32_t lonArc, + int32_t latArc, + uint16_t track, + uint8_t valid +) { + + tEraGlonassMsd_GpsPos lastPos = env->MSD_Data.pos; + + env->MSD_Data.pos.lat = latArc; + env->MSD_Data.pos.lon = lonArc; + + if (valid == 1){ + EraGlonassMsdCalcPosDelta(env, lastPos); + env->MSD_Data.MSD_Control.posStatus = 0x00; + env->MSD_Data.direction = 0xFF; + } else if (valid == 2){ + EraGlonassMsdCalcPosDelta(env, lastPos); + env->MSD_Data.MSD_Control.posStatus = 0x01; + env->MSD_Data.direction = track/2; + } + + env->MSD_Data.pos.lat += 0x80000000; // Make offset + env->MSD_Data.pos.lon += 0x80000000; + +} + + +void EraGlonassMsdSetPassengersNumber(tEraGlonassMsd *env, uint16_t value) { + // Check passengers number + if (value >= 1) { + env->MSD_Data.MSD_Control.passengers = value; // Passengers number available + } else { + env->MSD_Data.MSD_Control.passengers = 0x00; // Passengers number not available + } +} + +void EraGlonassMsdSetVehicleType(tEraGlonassMsd *env, eUveosGostVehicleType value) { + env->MSD_Data.MSD_Control.vehicleType = value; +} + +void EraGlonassMsdSetVIN(tEraGlonassMsd *env, char *vin, uint8_t vinLen) { + unsigned char ch = 0, i = 0; + // Set VIN + for (i = 0; i < 17; i++) { + + if (i < vinLen) { + ch = vin[i]; + } else { + ch = '0'; + } + + if (ch >= '0' && ch <= '9') { + ch -= 0x30; // Numbers are encoded with valuese 0x00 to 0x09 + } else if (ch >= 'A' && ch <= 'H') { + ch -= 0x37; + } else if (ch >= 'J' && ch <= 'N') { + ch -= 0x38; + } else if (ch == 'P') { + ch = 0x17; + } else if (ch >= 'R' && ch <= 'Z') { + ch -= 0x3A; + } else { + ch = '0' - 0x30; + } + + env->MSD_Data.vin[i] = ch; + } +} + +void EraGlonassMsdSetPropulsionStorageType( + tEraGlonassMsd *env, + eUveosGostVehiclePropulsionStorageType value +) { + env->MSD_Data.MSD_Control.includedTanks = 0b01111111; // Enable all tank type to be transmitted + + // Set propulsion system storage + env->MSD_Data.propulsion = value; +} + + +uint16_t sEraGlonassMsdEncodeOfControl(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + lastBit += vBitBufferAppendByte(raw, lastBit, data->msgId, 8); + + lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.activation ? 0x01 : 0x00, 1); + lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.testCall ? 0x01 : 0x00, 1); + lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.posStatus ? 0x01 : 0x00, 1); + + lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.vehicleType, 5); + + return lastBit; +} + + +uint16_t sEraGlonassMsdEncodeOfVin(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + for (int i = 0; i < 17; ++i) { + lastBit += vBitBufferAppendByte(raw, lastBit, ((uint8_t) data->vin[i]), 6); + } + + return lastBit; +} + + +uint16_t sEraGlonassMsdEncodeOfPropulsion(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + + uint8_t maxCountOfTanks = 0; + + if (data->msdId == MSD_V_1) { + maxCountOfTanks = 6; + } else if (data->msdId == MSD_V_2) { + maxCountOfTanks = 7; + } + + + uint8_t tanksInfoIncluded = !(data->MSD_Control.includedTanks >> maxCountOfTanks) && 0x1; + + if (tanksInfoIncluded) { + lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.includedTanks, maxCountOfTanks + 1); + + for (int i = 0; i < maxCountOfTanks; ++i) { + if ((data->MSD_Control.includedTanks >> i) && 0x1) { + lastBit += vBitBufferAppendByte(raw, lastBit, (data->propulsion >> i), 1); + } + } + } else { + lastBit += vBitBufferAppendByte(raw, lastBit, 0x1, 1); + } + + + return lastBit; +} + + +uint16_t sEraGlonassMsdEncodeOfTimestamp(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + lastBit += vBitBufferAppendBitsReverseBytes(raw, lastBit, (uint8_t *) &data->timestamp, 32); + + return lastBit; +} + + +uint16_t sEraGlonassMsdEncodeOfLocation(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + + lastBit += vBitBufferAppendBitsReverseBytes(raw, lastBit, (uint8_t *) &data->pos.lat, 32); + lastBit += vBitBufferAppendBitsReverseBytes(raw, lastBit, (uint8_t *) &data->pos.lon, 32); + + return lastBit; +} + + +uint16_t sEraGlonassMsdEncodeOfDirection(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + \ + lastBit += vBitBufferAppendByte(raw, lastBit, data->direction, 8); + + return lastBit; +} + +uint16_t sEraGlonassMsdEncodeOfRecentPositions(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + \ + if (data->MSD_Control.recentPos1) { + lastBit += vBitBufferAppendBits(raw, lastBit, (uint8_t *) &data->MSD_PosDelta[0].lat, 10); + lastBit += vBitBufferAppendBits(raw, lastBit, (uint8_t *) &data->MSD_PosDelta[0].lon, 10); + } + + if (data->MSD_Control.recentPos2) { + lastBit += vBitBufferAppendBits(raw, lastBit, (uint8_t *) &data->MSD_PosDelta[1].lat, 10); + lastBit += vBitBufferAppendBits(raw, lastBit, (uint8_t *) &data->MSD_PosDelta[1].lon, 10); + } + return lastBit; +} + + +uint16_t sEraGlonassMsdEncodeOfPassengersCount(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + + if (data->MSD_Control.passengers) { + lastBit += vBitBufferAppendBits(raw, lastBit, (uint8_t *) &data->MSD_Control.passengers, 8); + } + return lastBit; +} + +uint16_t sEraGlonassMsdEncodeOfV1FreeSpaceFix(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + + if (data->msdId == MSD_V_1) { + lastBit += vBitBufferAppendByte(raw, lastBit, 0x00, 8); + } + return lastBit; +} + + +uint16_t +sEraGlonassMsdEncodeOfAdditionalDataOID(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + lastBit += vBitBufferAppendByte(raw, lastBit, 0x03, 8);//lent of OID + + lastBit += vBitBufferAppendByte(raw, lastBit, 0x01, 8);//OID 1 + lastBit += vBitBufferAppendByte(raw, lastBit, 0x04, 8);//OID 2 + + if (data->msdId == MSD_V_1) { + lastBit += vBitBufferAppendByte(raw, lastBit, 0x01, 8);//OID 3 + } else if (data->msdId == MSD_V_2) { + lastBit += vBitBufferAppendByte(raw, lastBit, 0x02, 8);//OID 3 + } + + return lastBit; +} + +#define MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(FLAG) lastBit += vBitBufferAppendByte(raw, lastBit, (FLAG) == ERA_GLONASS_MSD_OPTIONAL_FLAG_ABSENT ? 0b0 : 0b1, 1); + +#define MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(FLAG) \ +if((FLAG) == ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_TRUE) { lastBit += vBitBufferAppendByte(raw, lastBit, 0b1 , 1);} \ +else if((FLAG) == ERA_GLONASS_MSD_OPTIONAL_FLAG_PRESENT_FALSE) { lastBit += vBitBufferAppendByte(raw, lastBit, 0b0, 1);} + +uint16_t sEraGlonassMsdEncodeOfAdditionalDataPayload( + tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit +) { + + lastBit += vBitBufferAppendByte(raw, lastBit, 0b0, 1); // enable extendable + //enable what present + lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalData.asi15Present ? 0b1 : 0b0, 1); + lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalData.diagnosticResult ? 0b1 : 0b0, 1); + lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalData.crashInfoPresent ? 0b1 : 0b0, 1); + + if (data->msdId == MSD_V_2) { + lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalData.coordSystem ? 0b1 : 0b0, + 1); // enable extendable + } + + if (data->additionalData.asi15Present) { + lastBit += vBitBufferAppendByte(raw, lastBit, ((uint8_t *) &data->additionalData.asi15)[1], 3); + lastBit += vBitBufferAppendByte(raw, lastBit, ((uint8_t *) &data->additionalData.asi15)[0], 8); + } + + if (data->additionalData.diagnosticResult) { + tMSD_DiagnosticResult *diagRes = data->additionalData.diagnosticResult; + + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->micConnectionFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->micFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->rightSpeakerFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->leftSpeakerFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->speakersFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->ignitionLineFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->uimFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->statusIndicatorFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->batteryFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->batteryVoltageLow); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->crashSensorFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->firmwareImageCorruption); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->commModuleInterfaceFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->gnssReceiverFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->raimProblem); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->gnssAntennaFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->commModuleFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->eventsMemoryOverflow); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->crashProfileMemoryOverflow); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->otherCriticalFailures); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(diagRes->otherNotCriticalFailures); + + + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->micConnectionFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->micFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->rightSpeakerFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->leftSpeakerFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->speakersFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->ignitionLineFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->uimFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->statusIndicatorFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->batteryFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->batteryVoltageLow); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->crashSensorFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->firmwareImageCorruption); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->commModuleInterfaceFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->gnssReceiverFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->raimProblem); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->gnssAntennaFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->commModuleFailure); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->eventsMemoryOverflow); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->crashProfileMemoryOverflow); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->otherCriticalFailures); + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(diagRes->otherNotCriticalFailures); + + } + + if (data->additionalData.crashInfoPresent) { + + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashFront) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashLeftSide) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashRightSide) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashRear) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashWithRollover) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashSide) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashFrontOrSide) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_PRESENT(data->additionalData.crashInfo.CrashOtherType) + + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashFront) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashLeftSide) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashRightSide) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashRear) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashWithRollover) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashSide) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashFrontOrSide) + MSD_TO_RAW_ADD_OPTIONAL_FLAG_VALUE(data->additionalData.crashInfo.CrashOtherType) + + } + + if (data->msdId == MSD_V_2) { + lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalData.coordSystem, 2); + } + + return lastBit; +} + +uint16_t sEraGlonassMsdEncodeOfAdditionalDataOctetString( + tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit +) { + + uint16_t octetStringOffset = lastBit + 8; + + uint16_t octetStringBitsLength = + sEraGlonassMsdEncodeOfAdditionalDataPayload(data, raw, octetStringOffset) - (octetStringOffset); + + uint8_t octetsCount = octetStringBitsLength / 8 + (octetStringBitsLength % 8 ? 1 : 0); + + lastBit += vBitBufferAppendByte(raw, lastBit, octetsCount, 8); + lastBit += octetsCount * 8; + + return lastBit; +} + +uint16_t sEraGlonassMsdEncodeOfAdditionalData(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + + lastBit = sEraGlonassMsdEncodeOfAdditionalDataOID(data, raw, lastBit); + lastBit = sEraGlonassMsdEncodeOfAdditionalDataOctetString(data, raw, lastBit); + + return lastBit; +} + +uint16_t sEraGlonassMsdEncodeOfMsdMainBody(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + + lastBit += vBitBufferAppendByte(raw, lastBit, 0b0, 1); + lastBit += vBitBufferAppendByte(raw, lastBit, data->additionalDataPresent ? 0b1 : 0b0, 1); + lastBit += vBitBufferAppendByte(raw, lastBit, 0b0, 1); +// lastBit+= vBitBufferAppendByte(raw,lastBit,data->MSD_Control.extraData,3); + lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.recentPos1 ? 0x01 : 0x00, 1); + lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.recentPos2 ? 0x01 : 0x00, 1); + lastBit += vBitBufferAppendByte(raw, lastBit, data->MSD_Control.passengers ? 0x01 : 0x00, 1); + + lastBit = sEraGlonassMsdEncodeOfControl(data, raw, lastBit); + lastBit = sEraGlonassMsdEncodeOfVin(data, raw, lastBit); + lastBit = sEraGlonassMsdEncodeOfPropulsion(data, raw, lastBit); + + lastBit = sEraGlonassMsdEncodeOfV1FreeSpaceFix(data, raw, lastBit); + + lastBit = sEraGlonassMsdEncodeOfTimestamp(data, raw, lastBit); + lastBit = sEraGlonassMsdEncodeOfLocation(data, raw, lastBit); + lastBit = sEraGlonassMsdEncodeOfDirection(data, raw, lastBit); + lastBit = sEraGlonassMsdEncodeOfRecentPositions(data, raw, lastBit); + lastBit = sEraGlonassMsdEncodeOfPassengersCount(data, raw, lastBit); + + if (data->additionalDataPresent) { + lastBit = sEraGlonassMsdEncodeOfAdditionalData(data, raw, lastBit); + } + + return lastBit; +} + +uint16_t sEraGlonassMsdEncodeV2BodyOctetString(tEraGlonassMsd_DataTypedef *data, unsigned char *raw, uint16_t lastBit) { + + //length of msd block + uint16_t octetStringOffset = lastBit + 8; + uint16_t octetStringBitsLength = + sEraGlonassMsdEncodeOfMsdMainBody(data, raw, octetStringOffset) - (octetStringOffset); + uint8_t octetsCount = octetStringBitsLength / 8 + (octetStringBitsLength % 8 ? 1 : 0); + + lastBit += vBitBufferAppendByte(raw, lastBit, octetsCount, 8); + + lastBit += octetsCount * 8; + + return lastBit; +} + + +uint16_t EraGlonassMsdEncode(tEraGlonassMsd *env, eEraGlonassMsd_Version msdVersion, uint8_t *encoded) { + env->MSD_Data.msdId = msdVersion; + + memset(encoded, '\0', ERA_GLONASS_MSD_ENCODED_BUFFER_LENGTH); // Clear + + uint16_t lastBit = 0; + + lastBit += vBitBufferAppendByte(encoded, lastBit, env->MSD_Data.msdId, 8); + + if (env->MSD_Data.msdId == MSD_V_1) { + lastBit = sEraGlonassMsdEncodeOfMsdMainBody(&env->MSD_Data, encoded, lastBit); + } else if (env->MSD_Data.msdId == MSD_V_2) { + lastBit = sEraGlonassMsdEncodeV2BodyOctetString(&env->MSD_Data, encoded, lastBit); + } + + size_t byteLength = lastBit / 8 + (lastBit % 8 ? 1 : 0); + return byteLength; +} + + + + + + + + + + + diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..91d35dc --- /dev/null +++ b/modular.json @@ -0,0 +1,22 @@ +{ + "dep": [ + { + "type": "git", + "provider": "Smart_Components_Aurus", + "repo": "UveosGostSettings" + }, + { + "type": "git", + "provider": "Smart_Components_Aurus", + "repo": "BitBufferOperations" + } + ], + "cmake": { + "inc_dirs": [ + "Inc" + ], + "srcs": [ + "Src/**.c" + ] + } +} \ No newline at end of file