Make signalLevel represent the SNR in dB, rather than a somewhat arbitrary amplitude value.

Include SNR values when dumping message contents.
This commit is contained in:
Oliver Jowett 2014-09-15 02:49:11 +01:00
parent 0378620445
commit 2e45a59986
4 changed files with 33 additions and 27 deletions

View file

@ -88,7 +88,7 @@
#define MODES_ASYNC_BUF_SAMPLES (MODES_ASYNC_BUF_SIZE / 2) // Each sample is 2 bytes #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_MSG_SQUELCH_LEVEL 0x02FF // Average signal strength limit #define MODES_MSG_SQUELCH_FACTOR 16 // Min SNR expressed as an amplitude ratio, scaled by 10. 20log(16/10) = 4.1dB
#define MODES_MSG_ENCODER_ERRS 3 // Maximum number of encoding errors #define MODES_MSG_ENCODER_ERRS 3 // Maximum number of encoding errors
// When changing, change also fixBitErrors() and modesInitErrorTable() !! // When changing, change also fixBitErrors() and modesInitErrorTable() !!

View file

@ -513,9 +513,9 @@ void interactiveShowData(void) {
snprintf(strFl, 6, "%5d", altitude); snprintf(strFl, 6, "%5d", altitude);
} }
printf("%06X %-4s %-4s %-8s %5s %3s %3s %7s %8s %3d %5d %2d\n", printf("%06X %-4s %-4s %-8s %5s %3s %3s %7s %8s %2d.%1d %5d %2d\n",
a->addr, strMode, strSquawk, a->flight, strFl, strGs, strTt, a->addr, strMode, strSquawk, a->flight, strFl, strGs, strTt,
strLat, strLon, signalAverage, msgs, (int)(now - a->seen)); strLat, strLon, signalAverage/5, 2*(signalAverage%5), msgs, (int)(now - a->seen));
} }
count++; count++;
} }

View file

@ -144,6 +144,7 @@ int detectModeA(uint16_t *m, struct modesMessage *mm)
int F1_sig, F1_noise; int F1_sig, F1_noise;
int F2_sig, F2_noise; int F2_sig, F2_noise;
int fSig, fNoise, fLevel, fLoLo; int fSig, fNoise, fLevel, fLoLo;
float snr;
// m[0] contains the energy from 0 -> 499 nS // m[0] contains the energy from 0 -> 499 nS
// m[1] contains the energy from 500 -> 999 nS // m[1] contains the energy from 500 -> 999 nS
@ -306,8 +307,8 @@ int detectModeA(uint16_t *m, struct modesMessage *mm)
if ((ModeABits < 3) || (ModeABits & 0xFFFF8808) || (ModeAErrs) ) if ((ModeABits < 3) || (ModeABits & 0xFFFF8808) || (ModeAErrs) )
{return (ModeABits = 0);} {return (ModeABits = 0);}
fSig = (fSig + 0x7F) >> 8; snr = 5 * 20.0 * log10f((float)(fSig + fNoise + 365) / (fNoise + 365)); // 365 to adjust for magnitude value offset
mm->signalLevel = ((fSig < 255) ? fSig : 255); mm->signalLevel = ((snr < 255) ? (uint8_t)round(snr) : 255);
return ModeABits; return ModeABits;
} }

View file

@ -1176,6 +1176,8 @@ void displayModesMessage(struct modesMessage *mm) {
if (mm->correctedbits != 0) if (mm->correctedbits != 0)
printf("No. of bit errors fixed: %d\n", mm->correctedbits); 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->msgtype == 0) { // DF 0 if (mm->msgtype == 0) { // DF 0
printf("DF 0: Short Air-Air Surveillance.\n"); printf("DF 0: Short Air-Air Surveillance.\n");
printf(" VS : %s\n", (mm->msg[0] & 0x04) ? "Ground" : "Airborne"); printf(" VS : %s\n", (mm->msg[0] & 0x04) ? "Ground" : "Airborne");
@ -1571,7 +1573,8 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
int high, i, errors, errors56, errorsTy; int high, i, errors, errors56, errorsTy;
uint16_t *pPreamble, *pPayload, *pPtr; uint16_t *pPreamble, *pPayload, *pPtr;
uint8_t theByte, theErrs; uint8_t theByte, theErrs;
int msglen, scanlen, sigStrength; int msglen, scanlen;
uint32_t sigLevel, noiseLevel;
pPreamble = &m[j]; pPreamble = &m[j];
pPayload = &m[j+MODES_PREAMBLE_SAMPLES]; pPayload = &m[j+MODES_PREAMBLE_SAMPLES];
@ -1677,10 +1680,8 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
// We should have 4 'bits' of 0/1 and 1/0 samples in the preamble, // We should have 4 'bits' of 0/1 and 1/0 samples in the preamble,
// so include these in the signal strength // so include these in the signal strength
sigStrength = (pPreamble[0]-pPreamble[1]) sigLevel = pPreamble[0] + pPreamble[2] + pPreamble[7] + pPreamble[9];
+ (pPreamble[2]-pPreamble[3]) noiseLevel = pPreamble[1] + pPreamble[3] + pPreamble[4] + pPreamble[6] + pPreamble[8];
+ (pPreamble[7]-pPreamble[6])
+ (pPreamble[9]-pPreamble[8]);
msglen = scanlen = MODES_LONG_MSG_BITS; msglen = scanlen = MODES_LONG_MSG_BITS;
for (i = 0; i < scanlen; i++) { for (i = 0; i < scanlen; i++) {
@ -1688,10 +1689,12 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
uint32_t b = *pPtr++; uint32_t b = *pPtr++;
if (a > b) if (a > b)
{theByte |= 1; if (i < 56) {sigStrength += (a-b);}} {theByte |= 1; if (i < 56) { sigLevel += a; noiseLevel += b; }}
else if (a < b) else if (a < b)
{/*theByte |= 0;*/ if (i < 56) {sigStrength += (b-a);}} {/*theByte |= 0;*/ if (i < 56) { sigLevel += b; noiseLevel += a; }}
else if (i >= MODES_SHORT_MSG_BITS) //(a == b), and we're in the long part of a frame else {
sigLevel += a; noiseLevel += a;
if (i >= MODES_SHORT_MSG_BITS) //(a == b), and we're in the long part of a frame
{errors++; /*theByte |= 0;*/} {errors++; /*theByte |= 0;*/}
else if (i >= 5) //(a == b), and we're in the short part of a frame else if (i >= 5) //(a == b), and we're in the short part of a frame
{scanlen = MODES_LONG_MSG_BITS; errors56 = ++errors;/*theByte |= 0;*/} {scanlen = MODES_LONG_MSG_BITS; errors56 = ++errors;/*theByte |= 0;*/}
@ -1699,6 +1702,7 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
{errorsTy = errors56 = ++errors; theErrs |= 1; /*theByte |= 0;*/} {errorsTy = errors56 = ++errors; theErrs |= 1; /*theByte |= 0;*/}
else //(a == b), and we're in the first bit of the message type part of a frame else //(a == b), and we're in the first bit of the message type part of a frame
{errorsTy = errors56 = ++errors; theErrs |= 1; theByte |= 1;} {errorsTy = errors56 = ++errors; theErrs |= 1; theByte |= 1;}
}
if ((i & 7) == 7) if ((i & 7) == 7)
{*pMsg++ = theByte;} {*pMsg++ = theByte;}
@ -1775,21 +1779,22 @@ void detectModeS(uint16_t *m, uint32_t mlen) {
} }
} }
// We measured signal strength over the first 56 bits. Don't forget to add 4 // adjust for magnitude zero offset
// for the preamble samples, so round up and divide by 60. sigLevel += 365*56;
sigStrength = (sigStrength + 29) / 60; noiseLevel += 365*56;
// When we reach this point, if error is small, and the signal strength is large enough // When we reach this point, if error is small, and the signal strength is large enough
// we may have a Mode S message on our hands. It may still be broken and the CRC may not // we may have a Mode S message on our hands. It may still be broken and the CRC may not
// be correct, but this can be handled by the next layer. // be correct, but this can be handled by the next layer.
if ( (msglen) if ( (msglen)
&& (sigStrength > MODES_MSG_SQUELCH_LEVEL) && ((sigLevel * 10) > (noiseLevel * MODES_MSG_SQUELCH_FACTOR)) // (sigLevel/noiseLevel) > (MODES_MSG_SQUELCH_FACTOR/10)
&& (errors <= MODES_MSG_ENCODER_ERRS) ) { && (errors <= MODES_MSG_ENCODER_ERRS) ) {
float snr;
// Set initial mm structure details // Set initial mm structure details
mm.timestampMsg = Modes.timestampBlk + (j*6); mm.timestampMsg = Modes.timestampBlk + (j*6);
sigStrength = (sigStrength + 0x7F) >> 8; snr = 5.0 * 20.0 * log10f( (float)sigLevel / noiseLevel ); // sig/noise levels are amplitudes, so square them when computing SNR
mm.signalLevel = ((sigStrength < 255) ? sigStrength : 255); mm.signalLevel = (snr > 255 ? 255 : (uint8_t)round(snr));
mm.phase_corrected = use_correction; mm.phase_corrected = use_correction;
// Decode the received message // Decode the received message