LCOV - code coverage report
Current view: top level - AP_ADSB/sagetech-sdk - sgDecodeMSR.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 31 83 37.3 %
Date: 2026-09-09 11:02:08 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @copyright Copyright (c) 2020 Sagetech, Inc. All rights reserved.
       3             :  *
       4             :  * @file sgDecodeMSR.c
       5             :  * @author jim.billmeyer
       6             :  *
       7             :  * @date Mar 17, 2021
       8             :  */
       9             : 
      10             : #include "sg.h"
      11             : #include <stdbool.h>
      12             : #include <stdint.h>
      13             : #include <string.h>
      14             : #include "sgUtil.h"
      15             : 
      16             : #define MS_PARAM_TOA (1 << 3)
      17             : #define MS_PARAM_ADSBVER (1 << 2)
      18             : #define MS_PARAM_CALLSIGN (1 << 1)
      19             : #define MS_PARAM_CATEMITTER (1 << 0)
      20             : 
      21             : #define MS_PARAM_AVLEN (1 << 7)
      22             : #define MS_PARAM_PRIORITY (1 << 6)
      23             : #define MS_PARAM_CAPCODES (1 << 5)
      24             : #define MS_PARAM_OPMODE (1 << 4)
      25             : #define MS_PARAM_NACP (1 << 3)
      26             : #define MS_PARAM_NACV (1 << 2)
      27             : #define MS_PARAM_SDA (1 << 1)
      28             : #define MS_PARAM_GVA (1 << 0)
      29             : 
      30             : #define MS_PARAM_NIC (1 << 7)
      31             : #define MS_PARAM_HEADING (1 << 6)
      32             : #define MS_PARAM_VRATE (1 << 5)
      33             : 
      34             : #define MS_CAP_B2LOW (1 << 3)
      35             : #define MS_CAP_UAT (1 << 1)
      36             : #define MS_CAP_TCR ((1 << 2) | (1 << 3))
      37             : #define MS_CAP_TSR (1 << 4)
      38             : #define MS_CAP_ARV (1 << 5)
      39             : #define MS_CAP_ADSB (1 << 6)
      40             : #define MS_CAP_TCAS (1 << 7)
      41             : 
      42             : #define MS_OP_GPS_LATFMT (1 << 7)
      43             : #define MS_OP_GPS_LONFMT (1 << 6)
      44             : #define MS_OP_TCAS_RA (1 << 5)
      45             : #define MS_OP_IDENT (1 << 4)
      46             : #define MS_OP_SINGLE_ANT (1 << 2)
      47             : 
      48             : /// the payload offset.
      49             : #define PBASE 4
      50             : 
      51             : /*
      52             :  * Documented in the header file.
      53             :  */
      54        4228 : bool sgDecodeMSR(uint8_t *buffer, sg_msr_t *msr)
      55             : {
      56        4228 :     memset(msr, 0, sizeof(sg_msr_t));
      57             : 
      58             :     uint8_t fields[3];
      59        4228 :     memcpy(fields, &buffer[PBASE + 0], 3);
      60             : 
      61        4228 :     if (buffer[PBASE + 1] == 0x6E && buffer[PBASE + 2] == 0x60)
      62             :     {
      63           0 :         msr->type = msrTypeV0;
      64             :     }
      65        4228 :     else if (buffer[PBASE + 1] == 0x7E && buffer[PBASE + 2] == 0xE0)
      66             :     {
      67           0 :         msr->type = msrTypeV1Airborne;
      68             :     }
      69        4228 :     else if (buffer[PBASE + 1] == 0xFE && buffer[PBASE + 2] == 0xE0)
      70             :     {
      71           0 :         msr->type = msrTypeV1Surface;
      72             :     }
      73        4228 :     else if (buffer[PBASE + 1] == 0x7F && buffer[PBASE + 2] == 0xE0)
      74             :     {
      75           0 :         msr->type = msrTypeV2Airborne;
      76             :     }
      77        4228 :     else if (buffer[PBASE + 1] == 0xFF && buffer[PBASE + 2] == 0xE0)
      78             :     {
      79           0 :         msr->type = msrTypeV2Surface;
      80             :     }
      81             : 
      82        4228 :     msr->flags = buffer[PBASE + 3];
      83        4228 :     msr->addr = toInt32(&buffer[PBASE + 4]) & 0xFFFFFF;
      84        4228 :     msr->addrType = buffer[PBASE + 7] & 0xFF;
      85             : 
      86        4228 :     uint8_t ofs = 8;
      87             : 
      88        4228 :     if (fields[0] & MS_PARAM_TOA)
      89             :     {
      90           0 :         msr->toa = toTOA(&buffer[PBASE + ofs]);
      91           0 :         ofs += 2;
      92             :     }
      93             : 
      94        4228 :     if (fields[0] & MS_PARAM_ADSBVER)
      95             :     {
      96           0 :         msr->version = buffer[PBASE + ofs];
      97           0 :         ofs++;
      98             :     }
      99             : 
     100        4228 :     if (fields[0] & MS_PARAM_CALLSIGN)
     101             :     {
     102        4228 :         memset(msr->callsign, 0, 9);
     103        4228 :         memcpy(msr->callsign, &buffer[PBASE + ofs], 8);
     104        4228 :         ofs += 8;
     105             :     }
     106             : 
     107        4228 :     if (fields[0] & MS_PARAM_CATEMITTER)
     108             :     {
     109           0 :         msr->emitter = buffer[PBASE + ofs];
     110           0 :         ofs++;
     111             :     }
     112             : 
     113        4228 :     if (fields[1] & MS_PARAM_AVLEN)
     114             :     {
     115           0 :         msr->size = buffer[PBASE + ofs];
     116           0 :         ofs++;
     117             :     }
     118             : 
     119        4228 :     if (fields[1] & MS_PARAM_PRIORITY)
     120             :     {
     121           0 :         msr->priority = buffer[PBASE + ofs];
     122           0 :         ofs++;
     123             :     }
     124             : 
     125        4228 :     if (fields[1] & MS_PARAM_CAPCODES)
     126             :     {
     127           0 :         uint8_t cap = buffer[PBASE + ofs + 0];
     128           0 :         msr->capability.b2low = cap & MS_CAP_B2LOW;
     129             : 
     130           0 :         cap = buffer[PBASE + ofs + 1];
     131           0 :         msr->capability.uat = cap & MS_CAP_UAT;
     132           0 :         msr->capability.tcr = (cap & MS_CAP_TCR) >> 2;
     133           0 :         msr->capability.tsr = cap & MS_CAP_TSR;
     134           0 :         msr->capability.arv = cap & MS_CAP_ARV;
     135           0 :         msr->capability.adsb = cap & MS_CAP_ADSB;
     136           0 :         msr->capability.tcas = cap & MS_CAP_TCAS;
     137             : 
     138           0 :         ofs += 3;
     139             :     }
     140             : 
     141        4228 :     if (fields[1] & MS_PARAM_OPMODE)
     142             :     {
     143           0 :         uint8_t op = buffer[PBASE + ofs + 0];
     144           0 :         msr->opMode.gpsLatFmt = (op & MS_OP_GPS_LATFMT) == 0;
     145           0 :         msr->opMode.gpsLonFmt = (op & MS_OP_GPS_LONFMT) == 0;
     146           0 :         msr->opMode.tcasRA = op & MS_OP_TCAS_RA;
     147           0 :         msr->opMode.ident = op & MS_OP_IDENT;
     148           0 :         msr->opMode.singleAnt = op & MS_OP_SINGLE_ANT;
     149             : 
     150           0 :         op = buffer[PBASE + ofs + 1];
     151           0 :         msr->opMode.gpsLatOfs = op >> 5;
     152           0 :         msr->opMode.gpsLonOfs = op & 0x17;
     153             : 
     154           0 :         ofs += 2;
     155             :     }
     156             : 
     157        4228 :     if (fields[1] & MS_PARAM_NACP)
     158             :     {
     159           0 :         msr->svQuality.nacp = buffer[PBASE + ofs];
     160           0 :         ofs++;
     161             :     }
     162             : 
     163        4228 :     if (fields[1] & MS_PARAM_NACV)
     164             :     {
     165           0 :         msr->svQuality.nacv = buffer[PBASE + ofs];
     166           0 :         ofs++;
     167             :     }
     168             : 
     169        4228 :     if (fields[1] & MS_PARAM_SDA)
     170             :     {
     171           0 :         uint8_t sda = buffer[PBASE + ofs];
     172           0 :         msr->svQuality.sda = (sda & 0x18) >> 3;
     173           0 :         msr->svQuality.silSupp = (sda & 0x04);
     174           0 :         msr->svQuality.sil = (sda & 0x03);
     175           0 :         ofs++;
     176             :     }
     177             : 
     178        4228 :     if (fields[1] & MS_PARAM_GVA)
     179             :     {
     180           0 :         msr->svQuality.gva = buffer[PBASE + ofs];
     181           0 :         ofs++;
     182             :     }
     183             : 
     184        4228 :     if (fields[2] & MS_PARAM_NIC)
     185             :     {
     186           0 :         msr->svQuality.nicBaro = buffer[PBASE + ofs];
     187           0 :         ofs++;
     188             :     }
     189             : 
     190        4228 :     if (fields[2] & MS_PARAM_HEADING)
     191             :     {
     192           0 :         msr->trackHeading = buffer[PBASE + ofs];
     193           0 :         ofs++;
     194             :     }
     195             : 
     196        4228 :     if (fields[2] & MS_PARAM_VRATE)
     197             :     {
     198           0 :         msr->vrateType = buffer[PBASE + ofs];
     199           0 :         ofs++;
     200             :     }
     201             : 
     202        4228 :     return true;
     203             : }

Generated by: LCOV version 1.14