mode_ac.c
Go to the documentation of this file.
1 // dump1090, a Mode S messages decoder for RTLSDR devices.
2 //
3 // Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are
9 // met:
10 //
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //
14 // * Redistributions in binary form must reproduce the above copyright
15 // notice, this list of conditions and the following disclaimer in the
16 // documentation and/or other materials provided with the distribution.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 
31 #include "dump1090.h"
32 //
33 // ===================== Mode A/C detection and decoding ===================
34 //
35 //
36 // This table is used to build the Mode A/C variable called ModeABits.Each
37 // bit period is inspected, and if it's value exceeds the threshold limit,
38 // then the value in this table is or-ed into ModeABits.
39 //
40 // At the end of message processing, ModeABits will be the decoded ModeA value.
41 //
42 // We can also flag noise in bits that should be zeros - the xx bits. Noise in
43 // these bits cause bits (31-16) in ModeABits to be set. Then at the end of message
44 // processing we can test for errors by looking at these bits.
45 //
46 uint32_t ModeABitTable[24] = {
47 0x00000000, // F1 = 1
48 0x00000010, // C1
49 0x00001000, // A1
50 0x00000020, // C2
51 0x00002000, // A2
52 0x00000040, // C4
53 0x00004000, // A4
54 0x40000000, // xx = 0 Set bit 30 if we see this high
55 0x00000100, // B1
56 0x00000001, // D1
57 0x00000200, // B2
58 0x00000002, // D2
59 0x00000400, // B4
60 0x00000004, // D4
61 0x00000000, // F2 = 1
62 0x08000000, // xx = 0 Set bit 27 if we see this high
63 0x04000000, // xx = 0 Set bit 26 if we see this high
64 0x00000080, // SPI
65 0x02000000, // xx = 0 Set bit 25 if we see this high
66 0x01000000, // xx = 0 Set bit 24 if we see this high
67 0x00800000, // xx = 0 Set bit 23 if we see this high
68 0x00400000, // xx = 0 Set bit 22 if we see this high
69 0x00200000, // xx = 0 Set bit 21 if we see this high
70 0x00100000, // xx = 0 Set bit 20 if we see this high
71 };
72 //
73 // This table is used to produce an error variable called ModeAErrs.Each
74 // inter-bit period is inspected, and if it's value falls outside of the
75 // expected range, then the value in this table is or-ed into ModeAErrs.
76 //
77 // At the end of message processing, ModeAErrs will indicate if we saw
78 // any inter-bit anomolies, and the bits that are set will show which
79 // bits had them.
80 //
81 uint32_t ModeAMidTable[24] = {
82 0x80000000, // F1 = 1 Set bit 31 if we see F1_C1 error
83 0x00000010, // C1 Set bit 4 if we see C1_A1 error
84 0x00001000, // A1 Set bit 12 if we see A1_C2 error
85 0x00000020, // C2 Set bit 5 if we see C2_A2 error
86 0x00002000, // A2 Set bit 13 if we see A2_C4 error
87 0x00000040, // C4 Set bit 6 if we see C3_A4 error
88 0x00004000, // A4 Set bit 14 if we see A4_xx error
89 0x40000000, // xx = 0 Set bit 30 if we see xx_B1 error
90 0x00000100, // B1 Set bit 8 if we see B1_D1 error
91 0x00000001, // D1 Set bit 0 if we see D1_B2 error
92 0x00000200, // B2 Set bit 9 if we see B2_D2 error
93 0x00000002, // D2 Set bit 1 if we see D2_B4 error
94 0x00000400, // B4 Set bit 10 if we see B4_D4 error
95 0x00000004, // D4 Set bit 2 if we see D4_F2 error
96 0x20000000, // F2 = 1 Set bit 29 if we see F2_xx error
97 0x08000000, // xx = 0 Set bit 27 if we see xx_xx error
98 0x04000000, // xx = 0 Set bit 26 if we see xx_SPI error
99 0x00000080, // SPI Set bit 15 if we see SPI_xx error
100 0x02000000, // xx = 0 Set bit 25 if we see xx_xx error
101 0x01000000, // xx = 0 Set bit 24 if we see xx_xx error
102 0x00800000, // xx = 0 Set bit 23 if we see xx_xx error
103 0x00400000, // xx = 0 Set bit 22 if we see xx_xx error
104 0x00200000, // xx = 0 Set bit 21 if we see xx_xx error
105 0x00100000, // xx = 0 Set bit 20 if we see xx_xx error
106 };
107 //
108 // The "off air" format is,,
109 // _F1_C1_A1_C2_A2_C4_A4_xx_B1_D1_B2_D2_B4_D4_F2_xx_xx_SPI_
110 //
111 // Bit spacing is 1.45uS, with 0.45uS high, and 1.00us low. This is a problem
112 // because we ase sampling at 2Mhz (500nS) so we are below Nyquist.
113 //
114 // The bit spacings are..
115 // F1 : 0.00,
116 // 1.45, 2.90, 4.35, 5.80, 7.25, 8.70,
117 // X : 10.15,
118 // : 11.60, 13.05, 14.50, 15.95, 17.40, 18.85,
119 // F2 : 20.30,
120 // X : 21.75, 23.20, 24.65
121 //
122 // This equates to the following sample point centers at 2Mhz.
123 // [ 0.0],
124 // [ 2.9], [ 5.8], [ 8.7], [11.6], [14.5], [17.4],
125 // [20.3],
126 // [23.2], [26.1], [29.0], [31.9], [34.8], [37.7]
127 // [40.6]
128 // [43.5], [46.4], [49.3]
129 //
130 // We know that this is a supposed to be a binary stream, so the signal
131 // should either be a 1 or a 0. Therefore, any energy above the noise level
132 // in two adjacent samples must be from the same pulse, so we can simply
133 // add the values together..
134 //
135 int detectModeA(uint16_t *m, struct modesMessage *mm)
136  {
137  int j, lastBitWasOne;
138  int ModeABits = 0;
139  int ModeAErrs = 0;
140  int byte, bit;
141  int thisSample, lastBit, lastSpace = 0;
142  int m0, m1, m2, m3, mPhase;
143  int n0, n1, n2 ,n3;
144  int F1_sig, F1_noise;
145  int F2_sig, F2_noise;
146  int fSig, fNoise, fLevel, fLoLo;
147 
148  // m[0] contains the energy from 0 -> 499 nS
149  // m[1] contains the energy from 500 -> 999 nS
150  // m[2] contains the energy from 1000 -> 1499 nS
151  // m[3] contains the energy from 1500 -> 1999 nS
152  //
153  // We are looking for a Frame bit (F1) whose width is 450nS, followed by
154  // 1000nS of quiet.
155  //
156  // The width of the frame bit is 450nS, which is 90% of our sample rate.
157  // Therefore, in an ideal world, all the energy for the frame bit will be
158  // in a single sample, preceeded by (at least) one zero, and followed by
159  // two zeros, Best case we can look for ...
160  //
161  // 0 - 1 - 0 - 0
162  //
163  // However, our samples are not phase aligned, so some of the energy from
164  // each bit could be spread over two consecutive samples. Worst case is
165  // that we sample half in one bit, and half in the next. In that case,
166  // we're looking for
167  //
168  // 0 - 0.5 - 0.5 - 0.
169 
170  m0 = m[0]; m1 = m[1];
171 
172  if (m0 >= m1) // m1 *must* be bigger than m0 for this to be F1
173  {return (0);}
174 
175  m2 = m[2]; m3 = m[3];
176 
177  //
178  // if (m2 <= m0), then assume the sample bob on (Phase == 0), so don't look at m3
179  if ((m2 <= m0) || (m2 < m3))
180  {m3 = m2; m2 = m0;}
181 
182  if ( (m3 >= m1) // m1 must be bigger than m3
183  || (m0 > m2) // m2 can be equal to m0 if ( 0,1,0,0 )
184  || (m3 > m2) ) // m2 can be equal to m3 if ( 0,1,0,0 )
185  {return (0);}
186 
187  // m0 = noise
188  // m1 = noise + (signal * X))
189  // m2 = noise + (signal * (1-X))
190  // m3 = noise
191  //
192  // Hence, assuming all 4 samples have similar amounts of noise in them
193  // signal = (m1 + m2) - ((m0 + m3) * 2)
194  // noise = (m0 + m3) / 2
195  //
196  F1_sig = (m1 + m2) - ((m0 + m3) << 1);
197  F1_noise = (m0 + m3) >> 1;
198 
199  if ( (F1_sig < MODEAC_MSG_SQUELCH_LEVEL) // minimum required F1 signal amplitude
200  || (F1_sig < (F1_noise << 2)) ) // minimum allowable Sig/Noise ratio 4:1
201  {return (0);}
202 
203  // If we get here then we have a potential F1, so look for an equally valid F2 20.3uS later
204  //
205  // Our F1 is centered somewhere between samples m[1] and m[2]. We can guestimate where F2 is
206  // by comparing the ratio of m1 and m2, and adding on 20.3 uS (40.6 samples)
207  //
208  mPhase = ((m2 * 20) / (m1 + m2));
209  byte = (mPhase + 812) / 20;
210  n0 = m[byte++]; n1 = m[byte++];
211 
212  if (n0 >= n1) // n1 *must* be bigger than n0 for this to be F2
213  {return (0);}
214 
215  n2 = m[byte++];
216  //
217  // if the sample bob on (Phase == 0), don't look at n3
218  //
219  if ((mPhase + 812) % 20)
220  {n3 = m[byte++];}
221  else
222  {n3 = n2; n2 = n0;}
223 
224  if ( (n3 >= n1) // n1 must be bigger than n3
225  || (n0 > n2) // n2 can be equal to n0 ( 0,1,0,0 )
226  || (n3 > n2) ) // n2 can be equal to n3 ( 0,1,0,0 )
227  {return (0);}
228 
229  F2_sig = (n1 + n2) - ((n0 + n3) << 1);
230  F2_noise = (n0 + n3) >> 1;
231 
232  if ( (F2_sig < MODEAC_MSG_SQUELCH_LEVEL) // minimum required F2 signal amplitude
233  || (F2_sig < (F2_noise << 2)) ) // maximum allowable Sig/Noise ratio 4:1
234  {return (0);}
235 
236  fSig = (F1_sig + F2_sig) >> 1;
237  fNoise = (F1_noise + F2_noise) >> 1;
238  fLoLo = fNoise + (fSig >> 2); // 1/2
239  fLevel = fNoise + (fSig >> 1);
240  lastBitWasOne = 1;
241  lastBit = F1_sig;
242  //
243  // Now step by a half ModeA bit, 0.725nS, which is 1.45 samples, which is 29/20
244  // No need to do bit 0 because we've already selected it as a valid F1
245  // Do several bits past the SPI to increase error rejection
246  //
247  for (j = 1, mPhase += 29; j < 48; mPhase += 29, j ++)
248  {
249  byte = 1 + (mPhase / 20);
250 
251  thisSample = m[byte] - fNoise;
252  if (mPhase % 20) // If the bit is split over two samples...
253  {thisSample += (m[byte+1] - fNoise);} // add in the second sample's energy
254 
255  // If we're calculating a space value
256  if (j & 1)
257  {lastSpace = thisSample;}
258 
259  else
260  {// We're calculating a new bit value
261  bit = j >> 1;
262  if (thisSample >= fLevel)
263  {// We're calculating a new bit value, and its a one
264  ModeABits |= ModeABitTable[bit--]; // or in the correct bit
265 
266  if (lastBitWasOne)
267  { // This bit is one, last bit was one, so check the last space is somewhere less than one
268  if ( (lastSpace >= (thisSample>>1)) || (lastSpace >= lastBit) )
269  {ModeAErrs |= ModeAMidTable[bit];}
270  }
271 
272  else
273  {// This bit,is one, last bit was zero, so check the last space is somewhere less than one
274  if (lastSpace >= (thisSample >> 1))
275  {ModeAErrs |= ModeAMidTable[bit];}
276  }
277 
278  lastBitWasOne = 1;
279  }
280 
281 
282  else
283  {// We're calculating a new bit value, and its a zero
284  if (lastBitWasOne)
285  { // This bit is zero, last bit was one, so check the last space is somewhere in between
286  if (lastSpace >= lastBit)
287  {ModeAErrs |= ModeAMidTable[bit];}
288  }
289 
290  else
291  {// This bit,is zero, last bit was zero, so check the last space is zero too
292  if (lastSpace >= fLoLo)
293  {ModeAErrs |= ModeAMidTable[bit];}
294  }
295 
296  lastBitWasOne = 0;
297  }
298 
299  lastBit = (thisSample >> 1);
300  }
301  }
302 
303  //
304  // Output format is : 00:A4:A2:A1:00:B4:B2:B1:00:C4:C2:C1:00:D4:D2:D1
305  //
306  if ((ModeABits < 3) || (ModeABits & 0xFFFF8808) || (ModeAErrs) )
307  {return (ModeABits = 0);}
308 
309  fSig = (fSig + 0x7F) >> 8;
310  mm->signalLevel = ((fSig < 255) ? fSig : 255);
311 
312  return ModeABits;
313  }
314 //
315 //=========================================================================
316 //
317 // Input format is : 00:A4:A2:A1:00:B4:B2:B1:00:C4:C2:C1:00:D4:D2:D1
318 //
319 int ModeAToModeC(unsigned int ModeA)
320  {
321  unsigned int FiveHundreds = 0;
322  unsigned int OneHundreds = 0;
323 
324  if ( (ModeA & 0xFFFF888B) // D1 set is illegal. D2 set is > 62700ft which is unlikely
325  || ((ModeA & 0x000000F0) == 0) ) // C1,,C4 cannot be Zero
326  {return -9999;}
327 
328  if (ModeA & 0x0010) {OneHundreds ^= 0x007;} // C1
329  if (ModeA & 0x0020) {OneHundreds ^= 0x003;} // C2
330  if (ModeA & 0x0040) {OneHundreds ^= 0x001;} // C4
331 
332  // Remove 7s from OneHundreds (Make 7->5, snd 5->7).
333  if ((OneHundreds & 5) == 5) {OneHundreds ^= 2;}
334 
335  // Check for invalid codes, only 1 to 5 are valid
336  if (OneHundreds > 5)
337  {return -9999;}
338 
339 //if (ModeA & 0x0001) {FiveHundreds ^= 0x1FF;} // D1 never used for altitude
340  if (ModeA & 0x0002) {FiveHundreds ^= 0x0FF;} // D2
341  if (ModeA & 0x0004) {FiveHundreds ^= 0x07F;} // D4
342 
343  if (ModeA & 0x1000) {FiveHundreds ^= 0x03F;} // A1
344  if (ModeA & 0x2000) {FiveHundreds ^= 0x01F;} // A2
345  if (ModeA & 0x4000) {FiveHundreds ^= 0x00F;} // A4
346 
347  if (ModeA & 0x0100) {FiveHundreds ^= 0x007;} // B1
348  if (ModeA & 0x0200) {FiveHundreds ^= 0x003;} // B2
349  if (ModeA & 0x0400) {FiveHundreds ^= 0x001;} // B4
350 
351  // Correct order of OneHundreds.
352  if (FiveHundreds & 1) {OneHundreds = 6 - OneHundreds;}
353 
354  return ((FiveHundreds * 5) + OneHundreds - 13);
355  }
356 //
357 //=========================================================================
358 //
359 void decodeModeAMessage(struct modesMessage *mm, int ModeA)
360  {
361  mm->msgtype = 32; // Valid Mode S DF's are DF-00 to DF-31.
362  // so use 32 to indicate Mode A/C
363 
364  mm->msgbits = 16; // Fudge up a Mode S style data stream
365  mm->msg[0] = (ModeA >> 8);
366  mm->msg[1] = (ModeA);
367 
368  // Fudge an ICAO address based on Mode A (remove the Ident bit)
369  // Use an upper address byte of FF, since this is ICAO unallocated
370  mm->addr = 0x00FF0000 | (ModeA & 0x0000FF7F);
371 
372  // Set the Identity field to ModeA
373  mm->modeA = ModeA & 0x7777;
375 
376  // Flag ident in flight status
377  mm->fs = ModeA & 0x0080;
378 
379  // Not much else we can tell from a Mode A/C reply.
380  // Just fudge up a few bits to keep other code happy
381  mm->crcok = 1;
382  mm->correctedbits = 0;
383  }
384 //
385 // ===================== Mode A/C detection and decoding ===================
386 //
int ModeAToModeC(unsigned int ModeA)
Definition: mode_ac.c:319
int detectModeA(uint16_t *m, struct modesMessage *mm)
Definition: mode_ac.c:135
constexpr double mm
Definition: AugerUnits.h:113
int correctedbits
Definition: dump1090.h:351
uint32_t addr
Definition: dump1090.h:353
constexpr double m2
Definition: AugerUnits.h:122
void decodeModeAMessage(struct modesMessage *mm, int ModeA)
Definition: mode_ac.c:359
#define MODEAC_MSG_SQUELCH_LEVEL
Definition: dump1090.h:96
unsigned char signalLevel
Definition: dump1090.h:357
#define MODES_ACFLAGS_SQUAWK_VALID
Definition: dump1090.h:132
constexpr double m3
Definition: AugerUnits.h:123
unsigned char msg[14]
Definition: dump1090.h:346
uint32_t ModeABitTable[24]
Definition: mode_ac.c:46
constexpr double m
Definition: AugerUnits.h:121
uint32_t ModeAMidTable[24]
Definition: mode_ac.c:81

, generated on Tue Sep 26 2023.