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:
parent
0378620445
commit
2e45a59986
|
@ -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() !!
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -383,4 +384,4 @@ void decodeModeAMessage(struct modesMessage *mm, int ModeA)
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// ===================== Mode A/C detection and decoding ===================
|
// ===================== Mode A/C detection and decoding ===================
|
||||||
//
|
//
|
||||||
|
|
47
mode_s.c
47
mode_s.c
|
@ -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,17 +1689,20 @@ 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 {
|
||||||
{errors++; /*theByte |= 0;*/}
|
sigLevel += a; noiseLevel += a;
|
||||||
else if (i >= 5) //(a == b), and we're in the short part of a frame
|
if (i >= MODES_SHORT_MSG_BITS) //(a == b), and we're in the long part of a frame
|
||||||
{scanlen = MODES_LONG_MSG_BITS; errors56 = ++errors;/*theByte |= 0;*/}
|
{errors++; /*theByte |= 0;*/}
|
||||||
else if (i) //(a == b), and we're in the message type part of a frame
|
else if (i >= 5) //(a == b), and we're in the short part of a frame
|
||||||
{errorsTy = errors56 = ++errors; theErrs |= 1; /*theByte |= 0;*/}
|
{scanlen = MODES_LONG_MSG_BITS; errors56 = ++errors;/*theByte |= 0;*/}
|
||||||
else //(a == b), and we're in the first bit of the message type part of a frame
|
else if (i) //(a == b), and we're in the message type part of a frame
|
||||||
{errorsTy = errors56 = ++errors; theErrs |= 1; theByte |= 1;}
|
{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
|
||||||
|
{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
|
||||||
|
|
Loading…
Reference in a new issue