[hamradio-commits] [dump1090] 57/389: Implemented Beast Binary output

Matthew Ernisse mernisse-guest at moszumanska.debian.org
Wed Nov 5 00:19:40 UTC 2014


This is an automated email from the git hooks/post-receive script.

mernisse-guest pushed a commit to branch master
in repository dump1090.

commit d3662bba80f6bab5fcfc501b8ec668ab1ef7f0d8
Author: Malcolm Robb <Support at ATTAvionics.com>
Date:   Sun Apr 7 16:22:02 2013 +0100

    Implemented Beast Binary output
---
 dump1090.c | 143 ++++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 95 insertions(+), 48 deletions(-)

diff --git a/dump1090.c b/dump1090.c
index 801bd70..85d4338 100644
--- a/dump1090.c
+++ b/dump1090.c
@@ -49,16 +49,22 @@
 #define MODES_DEFAULT_WIDTH        1000
 #define MODES_DEFAULT_HEIGHT       700
 #define MODES_ASYNC_BUF_NUMBER     12
-#define MODES_DATA_LEN             (16*16384)   /* 256k */
+#define MODES_ASYNC_BUF_SIZE       (16*16384)   /* 256k */
+#define MODES_ASYNC_BUF_SAMPLES    (MODES_ASYNC_BUF_SIZE / 2) /* Each sample is 2 bytes */
 #define MODES_AUTO_GAIN            -100         /* Use automatic gain. */
 #define MODES_MAX_GAIN             999999       /* Use max available gain. */
 
-#define MODES_PREAMBLE_US 8       /* microseconds */
-#define MODES_LONG_MSG_BITS 112
-#define MODES_SHORT_MSG_BITS 56
-#define MODES_FULL_LEN (MODES_PREAMBLE_US+MODES_LONG_MSG_BITS)
-#define MODES_LONG_MSG_BYTES (112/8)
-#define MODES_SHORT_MSG_BYTES (56/8)
+#define MODES_PREAMBLE_US        8              /* microseconds = bits */
+#define MODES_PREAMBLE_SAMPLES  (MODES_PREAMBLE_US       * 2)
+#define MODES_PREAMBLE_SIZE     (MODES_PREAMBLE_SAMPLES  * sizeof(uint16_t))
+#define MODES_LONG_MSG_BYTES     14
+#define MODES_SHORT_MSG_BYTES    7
+#define MODES_LONG_MSG_BITS     (MODES_LONG_MSG_BYTES    * 8)
+#define MODES_SHORT_MSG_BITS    (MODES_SHORT_MSG_BYTES   * 8)
+#define MODES_LONG_MSG_SAMPLES  (MODES_LONG_MSG_BITS     * 2)
+#define MODES_SHORT_MSG_SAMPLES (MODES_SHORT_MSG_BITS    * 2)
+#define MODES_LONG_MSG_SIZE     (MODES_LONG_MSG_SAMPLES  * sizeof(uint16_t))
+#define MODES_SHORT_MSG_SIZE    (MODES_SHORT_MSG_SAMPLES * sizeof(uint16_t))
 
 #define MODES_ICAO_CACHE_LEN 1024 /* Power of two required. */
 #define MODES_ICAO_CACHE_TTL 60   /* Time to live of cached addresses. */
@@ -129,6 +135,8 @@ struct {
     unsigned char *data;            /* Raw IQ samples buffer */
     uint16_t *magnitude;            /* Magnitude vector */
     uint32_t data_len;              /* Buffer length. */
+    long long timestampBlk;         /* Timestamp of the start of the current block */
+    long long timestampMsg;         /* Timestamp of the current message. */
     int fd;                         /* --ifile option file descriptor. */
     int data_ready;                 /* Data ready to be processed. */
     uint32_t *icao_cache;           /* Recently seen ICAO addresses cache. */
@@ -156,6 +164,7 @@ struct {
     int fix_errors;                 /* Single bit error correction if true. */
     int check_crc;                  /* Only display messages with good CRC. */
     int raw;                        /* Raw output format. */
+    int beast;                      /* Beast binary format output. */
     int debug;                      /* Debugging mode. */
     int net;                        /* Enable networking. */
     int net_only;                   /* Enable just networking. */
@@ -199,6 +208,8 @@ struct modesMessage {
     int errorbit;               /* Bit corrected. -1 if no bit corrected. */
     int aa1, aa2, aa3;          /* ICAO Address bytes 1 2 and 3 */
     int phase_corrected;        /* True if phase correction was applied. */
+    long long timestampMsg;     /* Timestamp of the message. */  
+    unsigned char signalLevel;  /* Signal Amplitude */
 
     /* DF 11 */
     int ca;                     /* Responder capabilities. */
@@ -236,6 +247,7 @@ struct modesMessage {
 void interactiveShowData(void);
 struct aircraft* interactiveReceiveData(struct modesMessage *mm);
 void modesSendRawOutput(struct modesMessage *mm);
+void modesSendBeastOutput(struct modesMessage *mm);
 void modesSendSBSOutput(struct modesMessage *mm, struct aircraft *a);
 void useModesMessage(struct modesMessage *mm);
 int fixSingleBitErrors(unsigned char *msg, int bits);
@@ -265,6 +277,7 @@ void modesInitConfig(void) {
     Modes.fix_errors = 1;
     Modes.check_crc = 1;
     Modes.raw = 0;
+    Modes.beast = 0;
     Modes.net = 0;
     Modes.net_only = 0;
     Modes.net_output_sbs_port = MODES_NET_OUTPUT_SBS_PORT;
@@ -289,20 +302,22 @@ void modesInit(void) {
      * in the message detection loop, back at the start of the next data
      * to process. This way we are able to also detect messages crossing
      * two reads. */
-    Modes.data_len = MODES_DATA_LEN + (MODES_FULL_LEN-1)*4;
     Modes.data_ready = 0;
+    Modes.timestampBlk = 0;
+    Modes.timestampMsg = 0;
     /* Allocate the ICAO address cache. We use two uint32_t for every
      * entry because it's a addr / timestamp pair for every entry. */
     Modes.icao_cache = malloc(sizeof(uint32_t)*MODES_ICAO_CACHE_LEN*2);
     memset(Modes.icao_cache,0,sizeof(uint32_t)*MODES_ICAO_CACHE_LEN*2);
     Modes.aircrafts = NULL;
     Modes.interactive_last_update = 0;
-    if ((Modes.data = malloc(Modes.data_len)) == NULL ||
-        (Modes.magnitude = malloc(Modes.data_len*2)) == NULL) {
+    if ((Modes.data = malloc(MODES_ASYNC_BUF_SIZE)) == NULL ||
+        (Modes.magnitude = malloc(MODES_ASYNC_BUF_SIZE+MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE)) == NULL) {
         fprintf(stderr, "Out of memory allocating data buffer.\n");
         exit(1);
     }
-    memset(Modes.data,127,Modes.data_len);
+    memset(Modes.data,127,MODES_ASYNC_BUF_SIZE);
+    memset(Modes.magnitude,0, MODES_ASYNC_BUF_SIZE+MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE);
 
     /* Populate the I/Q -> Magnitude lookup table. It is used because
      * sqrt or round may be expensive and may vary a lot depending on
@@ -396,12 +411,9 @@ void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) {
     MODES_NOTUSED(ctx);
 
     pthread_mutex_lock(&Modes.data_mutex);
-    if (len > MODES_DATA_LEN) len = MODES_DATA_LEN;
-    /* Move the last part of the previous buffer, that was not processed,
-     * on the start of the new buffer. */
-    memcpy(Modes.data, Modes.data+MODES_DATA_LEN, (MODES_FULL_LEN-1)*4);
+    if (len > MODES_ASYNC_BUF_SIZE) len = MODES_ASYNC_BUF_SIZE;
     /* Read the new data. */
-    memcpy(Modes.data+(MODES_FULL_LEN-1)*4, buf, len);
+    memcpy(Modes.data, buf, len);
     Modes.data_ready = 1;
     /* Signal to the other thread that new data is ready */
     pthread_cond_signal(&Modes.data_cond);
@@ -429,11 +441,8 @@ void readDataFromFile(void) {
             pthread_mutex_lock(&Modes.data_mutex);
         }
 
-        /* Move the last part of the previous buffer, that was not processed,
-         * on the start of the new buffer. */
-        memcpy(Modes.data, Modes.data+MODES_DATA_LEN, (MODES_FULL_LEN-1)*4);
-        toread = MODES_DATA_LEN;
-        p = Modes.data+(MODES_FULL_LEN-1)*4;
+        toread = MODES_ASYNC_BUF_SIZE;
+        p = Modes.data;
         while(toread) {
             nread = read(Modes.fd, p, toread);
             if (nread <= 0) {
@@ -462,7 +471,7 @@ void *readerThreadEntryPoint(void *arg) {
     if (Modes.filename == NULL) {
         rtlsdr_read_async(Modes.dev, rtlsdrCallback, NULL,
                               MODES_ASYNC_BUF_NUMBER,
-                              MODES_DATA_LEN);
+                              MODES_ASYNC_BUF_SIZE);
     } else {
         readDataFromFile();
     }
@@ -511,7 +520,7 @@ void dumpMagnitudeBar(int index, int magnitude) {
 void dumpMagnitudeVector(uint16_t *m, uint32_t offset) {
     uint32_t padding = 5; /* Show a few samples before the actual start. */
     uint32_t start = (offset < padding) ? 0 : offset-padding;
-    uint32_t end = offset + (MODES_PREAMBLE_US*2)+(MODES_SHORT_MSG_BITS*2) - 1;
+    uint32_t end = offset + (MODES_PREAMBLE_SAMPLES)+(MODES_SHORT_MSG_SAMPLES) - 1;
     uint32_t j;
 
     for (j = start; j <= end; j++) {
@@ -526,7 +535,7 @@ void dumpRawMessageJS(char *descr, unsigned char *msg,
 {
     int padding = 5; /* Show a few samples before the actual start. */
     int start = offset - padding;
-    int end = offset + (MODES_PREAMBLE_US*2)+(MODES_LONG_MSG_BITS*2) - 1;
+    int end = offset + (MODES_PREAMBLE_SAMPLES)+(MODES_LONG_MSG_SAMPLES) - 1;
     FILE *fp;
     int j, fix1 = -1, fix2 = -1;
 
@@ -665,7 +674,7 @@ int modesMessageLenByType(int type) {
  * of the error bit. Otherwise if fixing failed -1 is returned. */
 int fixSingleBitErrors(unsigned char *msg, int bits) {
     int j;
-    unsigned char aux[MODES_LONG_MSG_BITS/8];
+    unsigned char aux[MODES_LONG_MSG_BYTES];
 
     for (j = 0; j < bits; j++) {
         int byte = j/8;
@@ -696,7 +705,7 @@ int fixSingleBitErrors(unsigned char *msg, int bits) {
  * don't pass the checksum, and only in Aggressive Mode. */
 int fixTwoBitsErrors(unsigned char *msg, int bits) {
     int j, i;
-    unsigned char aux[MODES_LONG_MSG_BITS/8];
+    unsigned char aux[MODES_LONG_MSG_BYTES];
 
     for (j = 0; j < bits; j++) {
         int byte1 = j/8;
@@ -933,6 +942,8 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) {
 
     /* Work on our local copy */
     memcpy(mm->msg,msg,MODES_LONG_MSG_BYTES);
+    mm->timestampMsg = Modes.timestampMsg;
+    mm->signalLevel  = 0xA5;
     msg = mm->msg;
 
     /* Get the message type ASAP as other operations depend on this */
@@ -1228,19 +1239,21 @@ void displayModesMessage(struct modesMessage *mm) {
 /* Turn I/Q samples pointed by Modes.data into the magnitude vector
  * pointed by Modes.magnitude. */
 void computeMagnitudeVector(void) {
-    uint16_t *m = Modes.magnitude;
+    uint16_t *m = &Modes.magnitude[MODES_PREAMBLE_SAMPLES+MODES_LONG_MSG_SAMPLES];
     unsigned char *p = Modes.data;
     uint32_t j;
 
+    memcpy(Modes.magnitude,&Modes.magnitude[MODES_ASYNC_BUF_SAMPLES], MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE);
+
     /* Compute the magnitudo vector. It's just SQRT(I^2 + Q^2), but
      * we rescale to the 0-255 range to exploit the full resolution. */
-    for (j = 0; j < Modes.data_len; j += 2) {
-        int i = p[j]-127;
-        int q = p[j+1]-127;
+    for (j = 0; j < MODES_ASYNC_BUF_SAMPLES; j ++) {
+        int i = (*p++)-127;
+        int q = (*p++)-127;
 
         if (i < 0) i = -i;
         if (q < 0) q = -q;
-        m[j/2] = Modes.maglut[i*129+q];
+        *m++ = Modes.maglut[i*129+q];
     }
 }
 
@@ -1289,8 +1302,8 @@ int detectOutOfPhase(uint16_t *m) {
 void applyPhaseCorrection(uint16_t *m) {
     int j;
 
-    m += 16; /* Skip preamble. */
-    for (j = 0; j < (MODES_LONG_MSG_BITS-1)*2; j += 2) {
+    m += MODES_PREAMBLE_SAMPLES; /* Skip preamble. */
+    for (j = 0; j < MODES_LONG_MSG_SAMPLES; j += 2) {
         if (m[j] > m[j+1]) {
             /* One */
             m[j+2] = (m[j+2] * 5) / 4;
@@ -1306,8 +1319,8 @@ void applyPhaseCorrection(uint16_t *m) {
  * stream of bits and passed to the function to display it. */
 void detectModeS(uint16_t *m, uint32_t mlen) {
     unsigned char bits[MODES_LONG_MSG_BITS];
-    unsigned char msg[MODES_LONG_MSG_BITS/2];
-    uint16_t aux[MODES_LONG_MSG_BITS*2];
+    unsigned char msg[MODES_LONG_MSG_BYTES];
+    uint16_t aux[MODES_LONG_MSG_SAMPLES];
     uint32_t j;
     int use_correction = 0;
 
@@ -1334,7 +1347,7 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
      * 8   --
      * 9   -------------------
      */
-    for (j = 0; j < mlen - MODES_FULL_LEN*2; j++) {
+    for (j = 0; j < mlen; j++) {
         int low, high, delta, i, errors;
         int good_message = 0;
 
@@ -1393,12 +1406,13 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
             continue;
         }
         Modes.stat_valid_preamble++;
+        Modes.timestampMsg = Modes.timestampBlk + j;   
 
 good_preamble:
         /* If the previous attempt with this message failed, retry using
          * magnitude correction. */
         if (use_correction) {
-            memcpy(aux,m+j+MODES_PREAMBLE_US*2,sizeof(aux));
+            memcpy(aux,m+j+MODES_PREAMBLE_SAMPLES,sizeof(aux));
             if (j && detectOutOfPhase(m+j)) {
                 applyPhaseCorrection(m+j);
                 Modes.stat_out_of_phase++;
@@ -1409,9 +1423,9 @@ good_preamble:
         /* Decode all the next 112 bits, regardless of the actual message
          * size. We'll check the actual message type later. */
         errors = 0;
-        for (i = 0; i < MODES_LONG_MSG_BITS*2; i += 2) {
-            low = m[j+i+MODES_PREAMBLE_US*2];
-            high = m[j+i+MODES_PREAMBLE_US*2+1];
+        for (i = 0; i < MODES_LONG_MSG_SAMPLES; i += 2) {
+            low = m[j+i+MODES_PREAMBLE_SAMPLES];
+            high = m[j+i+MODES_PREAMBLE_SAMPLES+1];
             delta = low-high;
             if (delta < 0) delta = -delta;
 
@@ -1422,7 +1436,7 @@ good_preamble:
                  * is an effective way to detect if it's just random noise
                  * that was detected as a valid preamble. */
                 bits[i/2] = 2; /* error */
-                if (i < MODES_SHORT_MSG_BITS*2) errors++;
+                if (i < MODES_SHORT_MSG_SAMPLES) errors++;
             } else if (low > high) {
                 bits[i/2] = 1;
             } else {
@@ -1433,7 +1447,7 @@ good_preamble:
 
         /* Restore the original message if we used magnitude correction. */
         if (use_correction)
-            memcpy(m+j+MODES_PREAMBLE_US*2,aux,sizeof(aux));
+            memcpy(m+j+MODES_PREAMBLE_SAMPLES,aux,sizeof(aux));
 
         /* Pack bits into bytes */
         for (i = 0; i < MODES_LONG_MSG_BITS; i += 8) {
@@ -1455,8 +1469,8 @@ good_preamble:
          * to mark this as real message and not just noise? */
         delta = 0;
         for (i = 0; i < msglen*8*2; i += 2) {
-            delta += abs(m[j+i+MODES_PREAMBLE_US*2]-
-                         m[j+i+MODES_PREAMBLE_US*2+1]);
+            delta += abs(m[j+i+MODES_PREAMBLE_SAMPLES]-
+                         m[j+i+MODES_PREAMBLE_SAMPLES+1]);
         }
         delta /= msglen*4;
 
@@ -1556,8 +1570,11 @@ void useModesMessage(struct modesMessage *mm) {
             if (!Modes.raw && !Modes.onlyaddr) printf("\n");
         }
         /* Send data to connected clients. */
-        if (Modes.net) {
-            modesSendRawOutput(mm);  /* Feed raw output clients. */
+        if (Modes.net) {  /* Feed raw output clients. */
+            if (Modes.beast)
+                modesSendBeastOutput(mm);
+            else
+                modesSendRawOutput(mm);
         }
     }
 }
@@ -1867,7 +1884,7 @@ void snipMode(int level) {
     while ((i = getchar()) != EOF && (q = getchar()) != EOF) {
         if (abs(i-127) < level && abs(q-127) < level) {
             c++;
-            if (c > MODES_PREAMBLE_US*4) continue;
+            if (c > MODES_PREAMBLE_SIZE) continue;
         } else {
             c = 0;
         }
@@ -1997,6 +2014,32 @@ void modesSendAllClients(int service, void *msg, int len) {
     }
 }
 
+/* Write raw output in Beast Binary format with MLAT Counter to TCP clients */
+void modesSendBeastOutput(struct modesMessage *mm) {
+    char msg[64], *p = msg;
+    int  msgLen = mm->msgbits / 8;
+    char * pTimeStamp;
+    int  j;
+
+    *p++ = 0x1a;
+    if      (msgLen == MODES_SHORT_MSG_BYTES)
+      {*p++ = '2';}
+    else if (msgLen == MODES_LONG_MSG_BYTES)
+      {*p++ = '3';}
+    else
+      {return;}
+
+    *p++ = mm->signalLevel;
+
+    pTimeStamp = (char *) &mm->timestampMsg;
+    for (j = 5; j >= 0; j--) {
+        *p++ = pTimeStamp[j];
+    }
+
+    memcpy(p, mm->msg, msgLen);
+    modesSendAllClients(Modes.ros, msg, (msgLen + 9));
+}
+
 /* Write raw output to TCP clients. */
 void modesSendRawOutput(struct modesMessage *mm) {
     char msg[128], *p = msg;
@@ -2366,6 +2409,7 @@ void showHelp(void) {
 "--interactive-ttl <sec>  Remove from list if idle for <sec> (default: 60).\n"
 "--raw                    Show only messages hex values.\n"
 "--net                    Enable networking.\n"
+"--net-beast              TCP raw output in Beast binary format.\n"
 "--net-only               Enable just networking, no RTL device or file used.\n"
 "--net-ro-port <port>     TCP listening port for raw output (default: 30002).\n"
 "--net-ri-port <port>     TCP listening port for raw input (default: 30001).\n"
@@ -2440,6 +2484,8 @@ int main(int argc, char **argv) {
             Modes.raw = 1;
         } else if (!strcmp(argv[j],"--net")) {
             Modes.net = 1;
+        } else if (!strcmp(argv[j],"--net-beast")) {
+            Modes.beast = 1;
         } else if (!strcmp(argv[j],"--net-only")) {
             Modes.net = 1;
             Modes.net_only = 1;
@@ -2542,7 +2588,8 @@ int main(int argc, char **argv) {
          * stuff * at the same time. (This should only be useful with very
          * slow processors). */
         pthread_mutex_unlock(&Modes.data_mutex);
-        detectModeS(Modes.magnitude, Modes.data_len/2);
+        detectModeS(Modes.magnitude, MODES_ASYNC_BUF_SAMPLES);
+        Modes.timestampBlk += MODES_ASYNC_BUF_SAMPLES;
         backgroundTasks();
         pthread_mutex_lock(&Modes.data_mutex);
         if (Modes.exit) break;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/dump1090.git



More information about the pkg-hamradio-commits mailing list