Implemented Beast Binary output

This commit is contained in:
Malcolm Robb 2013-04-07 16:22:02 +01:00
parent ff0fe38722
commit d3662bba80

View file

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