Measure signal power / noise power (at least in 2.4MHz mode).
Switch signalLevel back to a power measurement, don't put SNR in there. But make it a 0.0 - 1.0 double so we're not scaling everywhere. Adjust for the amplitude offset when calculating power. Adapt everything else to the new scheme.
This commit is contained in:
parent
5beecb9f4f
commit
19082d92ea
|
@ -540,7 +540,7 @@ void demodulate2000(uint16_t *m, uint32_t mlen) {
|
|||
&& (errors <= MODES_MSG_ENCODER_ERRS) ) {
|
||||
// Set initial mm structure details
|
||||
mm.timestampMsg = Modes.timestampBlk + (j*6);
|
||||
mm.signalLevel = (snr > 255 ? 255 : (uint8_t)snr);
|
||||
mm.signalLevel = (365.0*60 + sigLevel + noiseLevel) * (365.0*60 + sigLevel + noiseLevel) / MAX_POWER / 60 / 60;
|
||||
mm.phase_corrected = use_correction;
|
||||
|
||||
// Decode the received message
|
||||
|
|
42
demod_2400.c
42
demod_2400.c
|
@ -153,10 +153,15 @@ void demodulate2400(uint16_t *m, uint32_t mlen) {
|
|||
struct modesMessage mm;
|
||||
unsigned char msg1[MODES_LONG_MSG_BYTES], msg2[MODES_LONG_MSG_BYTES], *msg;
|
||||
uint32_t j;
|
||||
uint32_t last_message_end = 0;
|
||||
|
||||
unsigned char *bestmsg;
|
||||
int bestscore, bestphase;
|
||||
|
||||
// noise floor:
|
||||
uint32_t noise_power_count = 0;
|
||||
uint64_t noise_power_sum = 0;
|
||||
|
||||
memset(&mm, 0, sizeof(mm));
|
||||
msg = msg1;
|
||||
|
||||
|
@ -167,6 +172,17 @@ void demodulate2400(uint16_t *m, uint32_t mlen) {
|
|||
int initial_phase, first_phase, last_phase, try_phase;
|
||||
int msglen;
|
||||
|
||||
// update noise for all samples that aren't part of a message
|
||||
// (we don't know if m[j] is or not, yet, so work one sample
|
||||
// in arrears)
|
||||
if (j > last_message_end+1) {
|
||||
// There seems to be a weird compiler bug I'm hitting here..
|
||||
// if you compute the square directly, it occasionally gets mangled.
|
||||
uint64_t s = TRUE_AMPLITUDE(m[j-1]);
|
||||
noise_power_sum += s * s;
|
||||
noise_power_count++;
|
||||
}
|
||||
|
||||
// Look for a message starting at around sample 0 with phase offset 3..7
|
||||
|
||||
// Ideal sample values for preambles with different phase
|
||||
|
@ -403,6 +419,28 @@ void demodulate2400(uint16_t *m, uint32_t mlen) {
|
|||
mm.score = bestscore;
|
||||
mm.bFlags = mm.correctedbits = 0;
|
||||
|
||||
// measure signal power
|
||||
{
|
||||
uint64_t signal_power_sum = 0;
|
||||
double signal_power;
|
||||
int signal_len = msglen*12/5 + 1;
|
||||
int k;
|
||||
|
||||
for (k = 0; k < signal_len; ++k) {
|
||||
uint64_t s = TRUE_AMPLITUDE(m[j+19+k]);
|
||||
signal_power_sum += s * s;
|
||||
}
|
||||
|
||||
mm.signalLevel = signal_power = signal_power_sum / MAX_POWER / signal_len;
|
||||
Modes.stats_current.signal_power_sum += signal_power;
|
||||
Modes.stats_current.signal_power_count ++;
|
||||
|
||||
if (signal_power > Modes.stats_current.peak_signal_power)
|
||||
Modes.stats_current.peak_signal_power = signal_power;
|
||||
if (signal_power > 0.50119)
|
||||
Modes.stats_current.strong_signal_count++; // signal power above -3dBFS
|
||||
}
|
||||
|
||||
// Decode the received message
|
||||
if (decodeModesMessage(&mm, bestmsg) < 0)
|
||||
continue;
|
||||
|
@ -426,10 +464,14 @@ void demodulate2400(uint16_t *m, uint32_t mlen) {
|
|||
// where the preamble of the second message clobbered the last
|
||||
// few bits of the first message, but the message bits didn't
|
||||
// overlap)
|
||||
last_message_end = j + (8 + msglen)*12/5;
|
||||
j += (8 + msglen - 8)*12/5 - 1;
|
||||
|
||||
// Pass data to the next layer
|
||||
useModesMessage(&mm);
|
||||
}
|
||||
|
||||
Modes.stats_current.noise_power_sum += (noise_power_sum / MAX_POWER / noise_power_count);
|
||||
Modes.stats_current.noise_power_count ++;
|
||||
}
|
||||
|
||||
|
|
|
@ -209,6 +209,11 @@
|
|||
|
||||
#define MODES_NOTUSED(V) ((void) V)
|
||||
|
||||
// adjust for zero offset of amplitude values
|
||||
#define TRUE_AMPLITUDE(x) ((x) + 365)
|
||||
#define MAX_AMPLITUDE TRUE_AMPLITUDE(65535)
|
||||
#define MAX_POWER (1.0 * MAX_AMPLITUDE * MAX_AMPLITUDE)
|
||||
|
||||
// Include subheaders after all the #defines are in place
|
||||
|
||||
#include "anet.h"
|
||||
|
@ -235,7 +240,7 @@ struct client {
|
|||
struct aircraft {
|
||||
uint32_t addr; // ICAO address
|
||||
char flight[16]; // Flight number
|
||||
unsigned char signalLevel[8]; // Last 8 Signal Amplitudes
|
||||
double signalLevel[8]; // Last 8 Signal Amplitudes
|
||||
int altitude; // Altitude
|
||||
int speed; // Velocity
|
||||
int track; // Angle of flight
|
||||
|
@ -402,7 +407,7 @@ struct modesMessage {
|
|||
int phase_corrected; // True if phase correction was applied
|
||||
uint64_t timestampMsg; // Timestamp of the message
|
||||
int remote; // If set this message is from a remote station
|
||||
unsigned char signalLevel; // Signal Amplitude
|
||||
double signalLevel; // RSSI, in the range [0..1], as a fraction of full-scale power
|
||||
int score;
|
||||
|
||||
// DF 11, DF 17
|
||||
|
|
|
@ -68,16 +68,18 @@ static uint64_t mstime(void) {
|
|||
// of aircraft
|
||||
//
|
||||
struct aircraft *interactiveCreateAircraft(struct modesMessage *mm) {
|
||||
static struct aircraft zeroAircraft;
|
||||
struct aircraft *a = (struct aircraft *) malloc(sizeof(*a));
|
||||
int i;
|
||||
|
||||
// Default everything to zero/NULL
|
||||
memset(a, 0, sizeof(*a));
|
||||
*a = zeroAircraft;
|
||||
|
||||
// Now initialise things that should not be 0/NULL to their defaults
|
||||
a->addr = mm->addr;
|
||||
a->lat = a->lon = 0.0;
|
||||
memset(a->signalLevel, mm->signalLevel, 8); // First time, initialise everything
|
||||
// to the first signal strength
|
||||
for (i = 0; i < 8; ++i)
|
||||
a->signalLevel[i] = mm->signalLevel; // First time, initialise everything
|
||||
// to the first signal strength
|
||||
|
||||
// mm->msgtype 32 is used to represent Mode A/C. These values can never change, so
|
||||
// set them once here during initialisation, and don't bother to set them every
|
||||
|
@ -521,7 +523,7 @@ void interactiveShowData(void) {
|
|||
|
||||
if (Modes.interactive_rtl1090 == 0) {
|
||||
printf (
|
||||
"Hex Mode Sqwk Flight Alt Spd Hdg Lat Long Sig Msgs Ti%c\n", progress);
|
||||
"Hex Mode Sqwk Flight Alt Spd Hdg Lat Long RSSI Msgs Ti%c\n", progress);
|
||||
} else {
|
||||
printf (
|
||||
"Hex Flight Alt V/S GS TT SSR G*456^ Msgs Seen %c\n", progress);
|
||||
|
@ -576,9 +578,9 @@ void interactiveShowData(void) {
|
|||
char strMode[5] = " ";
|
||||
char strLat[8] = " ";
|
||||
char strLon[9] = " ";
|
||||
unsigned char * pSig = a->signalLevel;
|
||||
unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
|
||||
pSig[4] + pSig[5] + pSig[6] + pSig[7] + 3) >> 3;
|
||||
double * pSig = a->signalLevel;
|
||||
double signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
|
||||
pSig[4] + pSig[5] + pSig[6] + pSig[7]) / 8.0;
|
||||
|
||||
if ((flags & MODEAC_MSG_FLAG) == 0) {
|
||||
strMode[0] = 'S';
|
||||
|
@ -599,9 +601,9 @@ void interactiveShowData(void) {
|
|||
snprintf(strFl, 6, "%5d", altitude);
|
||||
}
|
||||
|
||||
printf("%06X %-4s %-4s %-8s %5s %3s %3s %7s %8s %2d.%1d %5d %2d\n",
|
||||
a->addr, strMode, strSquawk, a->flight, strFl, strGs, strTt,
|
||||
strLat, strLon, signalAverage/5, 2*(signalAverage%5), msgs, (int)(now - a->seen));
|
||||
printf("%06X %-4s %-4s %-8s %5s %3s %3s %7s %8s %5.1f %5d %2d\n",
|
||||
a->addr, strMode, strSquawk, a->flight, strFl, strGs, strTt,
|
||||
strLat, strLon, 10 * log10(signalAverage), msgs, (int)(now - a->seen));
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
|
10
mode_ac.c
10
mode_ac.c
|
@ -144,7 +144,6 @@ int detectModeA(uint16_t *m, struct modesMessage *mm)
|
|||
int F1_sig, F1_noise;
|
||||
int F2_sig, F2_noise;
|
||||
int fSig, fNoise, fLevel, fLoLo;
|
||||
int snr;
|
||||
|
||||
// m[0] contains the energy from 0 -> 499 nS
|
||||
// m[1] contains the energy from 500 -> 999 nS
|
||||
|
@ -307,14 +306,7 @@ int detectModeA(uint16_t *m, struct modesMessage *mm)
|
|||
if ((ModeABits < 3) || (ModeABits & 0xFFFF8808) || (ModeAErrs) )
|
||||
{return (ModeABits = 0);}
|
||||
|
||||
// snr = 5 * 20log10(fSig / (fSig+fNoise)) (in units of 0.2dB)
|
||||
// = 100log10(fSig) - 100log10(fSig+fNoise)
|
||||
while (fSig > 65535 || (fSig + fNoise) > 65535) {
|
||||
fSig >>= 1;
|
||||
fNoise >>= 1;
|
||||
}
|
||||
snr = Modes.log10lut[fSig] - Modes.log10lut[fSig + fNoise];
|
||||
mm->signalLevel = ((snr < 255) ? (uint8_t)snr : 255);
|
||||
mm->signalLevel = 1.0 * TRUE_AMPLITUDE(fSig + fNoise) * TRUE_AMPLITUDE(fSig + fNoise) / MAX_POWER;
|
||||
|
||||
return ModeABits;
|
||||
}
|
||||
|
|
3
mode_s.c
3
mode_s.c
|
@ -1005,7 +1005,8 @@ void displayModesMessage(struct modesMessage *mm) {
|
|||
if (mm->correctedbits != 0)
|
||||
printf("No. of bit errors fixed: %d\n", mm->correctedbits);
|
||||
|
||||
printf("SNR: %d.%d dB\n", mm->signalLevel/5, 2*(mm->signalLevel%5));
|
||||
if (mm->signalLevel > 0)
|
||||
printf("RSSI: %.1f dBFS\n", 10 * log10(mm->signalLevel));
|
||||
|
||||
if (mm->score)
|
||||
printf("Score: %d\n", mm->score);
|
||||
|
|
9
net_io.c
9
net_io.c
|
@ -293,7 +293,7 @@ void modesSendBeastOutput(struct modesMessage *mm) {
|
|||
if (0x1A == ch) {*p++ = ch; }
|
||||
}
|
||||
|
||||
*p++ = (ch = mm->signalLevel);
|
||||
*p++ = ch = (char) round(mm->signalLevel * 255);
|
||||
if (0x1A == ch) {*p++ = ch; }
|
||||
|
||||
for (j = 0; j < msgLen; j++) {
|
||||
|
@ -568,7 +568,8 @@ int decodeBinMessage(struct client *c, char *p) {
|
|||
if (0x1A == ch) {p++;}
|
||||
}
|
||||
|
||||
mm.signalLevel = ch = *p++; // Grab the signal level
|
||||
ch = *p++; // Grab the signal level
|
||||
mm.signalLevel = ((unsigned)ch / 255.0);
|
||||
if (0x1A == ch) {p++;}
|
||||
|
||||
for (j = 0; j < msgLen; j++) { // and the data
|
||||
|
@ -627,7 +628,7 @@ int decodeHexMessage(struct client *c, char *hex) {
|
|||
// Mark messages received over the internet as remote so that we don't try to
|
||||
// pass them off as being received by this instance when forwarding them
|
||||
mm.remote = 1;
|
||||
mm.signalLevel = 0xFF;
|
||||
mm.signalLevel = 0.0;
|
||||
|
||||
// Remove spaces on the left and on the right
|
||||
while(l && isspace(hex[l-1])) {
|
||||
|
@ -644,7 +645,7 @@ int decodeHexMessage(struct client *c, char *hex) {
|
|||
|
||||
switch(hex[0]) {
|
||||
case '<': {
|
||||
mm.signalLevel = (hexDigitVal(hex[13])<<4) | hexDigitVal(hex[14]);
|
||||
mm.signalLevel = ((hexDigitVal(hex[13])<<4) | hexDigitVal(hex[14])) / 255.0;
|
||||
hex += 15; l -= 16; // Skip <, timestamp and siglevel, and ;
|
||||
break;}
|
||||
|
||||
|
|
33
stats.c
33
stats.c
|
@ -110,6 +110,22 @@ void display_stats(struct stats *st) {
|
|||
printf("%d phase enhancement attempts\n", st->out_of_phase);
|
||||
display_demod_stats("phase enhanced ", &st->demod_phasecorrected);
|
||||
}
|
||||
|
||||
if (st->noise_power_count) {
|
||||
printf("%.1f dBFS noise floor\n",
|
||||
10 * log10(st->noise_power_sum / st->noise_power_count));
|
||||
}
|
||||
|
||||
if (st->signal_power_count) {
|
||||
printf("%.1f dBFS mean signal power\n",
|
||||
10 * log10(st->signal_power_sum / st->signal_power_count));
|
||||
}
|
||||
|
||||
printf("%.1f dBFS peak signal power\n",
|
||||
10 * log10(st->peak_signal_power));
|
||||
|
||||
printf("%u messages with signal power above -3dBFS\n",
|
||||
st->strong_signal_count);
|
||||
}
|
||||
|
||||
printf("%d remote messages accepted\n"
|
||||
|
@ -206,6 +222,23 @@ void add_stats(const struct stats *st1, const struct stats *st2, struct stats *t
|
|||
// total messages:
|
||||
target->messages_total = st1->messages_total + st2->messages_total;
|
||||
|
||||
// noise floor:
|
||||
target->noise_power_sum = st1->noise_power_sum + st2->noise_power_sum;
|
||||
target->noise_power_count = st1->noise_power_count + st2->noise_power_count;
|
||||
|
||||
// mean signal power:
|
||||
target->signal_power_sum = st1->signal_power_sum + st2->signal_power_sum;
|
||||
target->signal_power_count = st1->signal_power_count + st2->signal_power_count;
|
||||
|
||||
// peak signal power seen
|
||||
if (st1->peak_signal_power > st2->peak_signal_power)
|
||||
target->peak_signal_power = st1->peak_signal_power;
|
||||
else
|
||||
target->peak_signal_power = st2->peak_signal_power;
|
||||
|
||||
// strong signals
|
||||
target->strong_signal_count = st1->strong_signal_count + st2->strong_signal_count;
|
||||
|
||||
// CPR decoding:
|
||||
target->cpr_global_ok = st1->cpr_global_ok + st2->cpr_global_ok;
|
||||
target->cpr_global_bad = st1->cpr_global_bad + st2->cpr_global_bad;
|
||||
|
|
14
stats.h
14
stats.h
|
@ -91,6 +91,20 @@ struct stats {
|
|||
|
||||
struct timespec cputime;
|
||||
|
||||
// noise floor:
|
||||
double noise_power_sum;
|
||||
uint32_t noise_power_count;
|
||||
|
||||
// mean signal power:
|
||||
double signal_power_sum;
|
||||
uint32_t signal_power_count;
|
||||
|
||||
// peak signal power seen
|
||||
double peak_signal_power;
|
||||
|
||||
// number of signals with power > -3dBFS
|
||||
uint32_t strong_signal_count;
|
||||
|
||||
// remote messages:
|
||||
unsigned int remote_accepted;
|
||||
unsigned int remote_rejected;
|
||||
|
|
Loading…
Reference in a new issue