@@ -226,6 +226,8 @@ struct demodulator_state_s
226
226
signed int data_clock_pll ; // PLL for data clock recovery.
227
227
// It is incremented by pll_step_per_sample
228
228
// for each audio sample.
229
+ // Must be 32 bits!!!
230
+ // So far, this is the case for every compiler used.
229
231
230
232
signed int prev_d_c_pll ; // Previous value of above, before
231
233
// incrementing, to detect overflows.
@@ -238,6 +240,18 @@ struct demodulator_state_s
238
240
239
241
int lfsr ; // Descrambler shift register.
240
242
243
+ // This is for detecting phase lock to incoming signal.
244
+
245
+ int good_flag ; // Set if transition is near where expected,
246
+ // i.e. at a good time.
247
+ int bad_flag ; // Set if transition is not where expected,
248
+ // i.e. at a bad time.
249
+ unsigned char good_hist ; // History of good transitions for past octet.
250
+ unsigned char bad_hist ; // History of bad transitions for past octet.
251
+ unsigned int score ; // History of whether good triumphs over bad
252
+ // for past 32 symbols.
253
+ int data_detect ; // True when locked on to signal.
254
+
241
255
} slicer [MAX_SLICERS ]; // Actual number in use is num_slicers.
242
256
// Should be in range 1 .. MAX_SLICERS,
243
257
/*
@@ -336,5 +350,100 @@ struct demodulator_state_s
336
350
337
351
};
338
352
353
+
354
+ /*-------------------------------------------------------------------
355
+ *
356
+ * Name: pll_dcd_signal_transition2
357
+ * dcd_each_symbol2
358
+ *
359
+ * Purpose: New DCD strategy for 1.6.
360
+ *
361
+ * Inputs: D Pointer to demodulator state.
362
+ *
363
+ * chan Radio channel: 0 to MAX_CHANS - 1
364
+ *
365
+ * subchan Which of multiple demodulators: 0 to MAX_SUBCHANS - 1
366
+ *
367
+ * slice Slicer number: 0 to MAX_SLICERS - 1.
368
+ *
369
+ * dpll_phase Signed 32 bit counter for DPLL phase.
370
+ * Wraparound is where data is sampled.
371
+ * Ideally transitions would occur close to 0.
372
+ *
373
+ * Output: D->slicer[slice].data_detect - true when PLL is locked to incoming signal.
374
+ *
375
+ * Description: From the beginning, DCD was based on finding several flag octets
376
+ * in a row and dropping when eight bits with no transitions.
377
+ * It was less than ideal but we limped along with it all these years.
378
+ * This fell apart when FX.25 came along and a couple of the
379
+ * correlation tags have eight "1" bits in a row.
380
+ *
381
+ * Our new strategy is to keep a running score of how well demodulator
382
+ * output transitions match to where expected.
383
+ *
384
+ *--------------------------------------------------------------------*/
385
+
386
+ #include "hdlc_rec.h" // for dcd_change
387
+
388
+ // These are good for 1200 bps AFSK.
389
+ // Might want to override for other modems.
390
+
391
+ #ifndef DCD_THRESH_ON
392
+ #define DCD_THRESH_ON 30 // Hysteresis: Can miss 2 out of 32 for detecting lock.
393
+ // 31 is best for TNC Test CD. 30 almost as good.
394
+ // 30 better for 1200 regression test.
395
+ #endif
396
+
397
+ #ifndef DCD_THRESH_OFF
398
+ #define DCD_THRESH_OFF 6 // Might want a little more fine tuning.
399
+ #endif
400
+
401
+ #ifndef DCD_GOOD_WIDTH
402
+ #define DCD_GOOD_WIDTH 512 // No more than 1024!!!
403
+ #endif
404
+
405
+ __attribute__((always_inline ))
406
+ inline static void pll_dcd_signal_transition2 (struct demodulator_state_s * D , int slice , int dpll_phase )
407
+ {
408
+ if (dpll_phase > - DCD_GOOD_WIDTH * 1024 * 1024 && dpll_phase < DCD_GOOD_WIDTH * 1024 * 1024 ) {
409
+ D -> slicer [slice ].good_flag = 1 ;
410
+ }
411
+ else {
412
+ D -> slicer [slice ].bad_flag = 1 ;
413
+ }
414
+ }
415
+
416
+ __attribute__((always_inline ))
417
+ inline static void pll_dcd_each_symbol2 (struct demodulator_state_s * D , int chan , int subchan , int slice )
418
+ {
419
+ D -> slicer [slice ].good_hist <<= 1 ;
420
+ D -> slicer [slice ].good_hist |= D -> slicer [slice ].good_flag ;
421
+ D -> slicer [slice ].good_flag = 0 ;
422
+
423
+ D -> slicer [slice ].bad_hist <<= 1 ;
424
+ D -> slicer [slice ].bad_hist |= D -> slicer [slice ].bad_flag ;
425
+ D -> slicer [slice ].bad_flag = 0 ;
426
+
427
+ D -> slicer [slice ].score <<= 1 ;
428
+ // 2 is to detect 'flag' patterns with 2 transitions per octet.
429
+ D -> slicer [slice ].score |= (signed )__builtin_popcount (D -> slicer [slice ].good_hist )
430
+ - (signed )__builtin_popcount (D -> slicer [slice ].bad_hist ) >= 2 ;
431
+
432
+ int s = __builtin_popcount (D -> slicer [slice ].score );
433
+ if (s >= DCD_THRESH_ON ) {
434
+ if (D -> slicer [slice ].data_detect == 0 ) {
435
+ D -> slicer [slice ].data_detect = 1 ;
436
+ dcd_change (chan , subchan , slice , D -> slicer [slice ].data_detect );
437
+ }
438
+ }
439
+ else if (s <= DCD_THRESH_OFF ) {
440
+ if (D -> slicer [slice ].data_detect != 0 ) {
441
+ D -> slicer [slice ].data_detect = 0 ;
442
+ dcd_change (chan , subchan , slice , D -> slicer [slice ].data_detect );
443
+ }
444
+ }
445
+ }
446
+
447
+
339
448
#define FSK_DEMOD_STATE_H 1
340
- #endif
449
+ #endif
0 commit comments