|
68 | 68 | #define SPANDSP_USE_FIXED_POINTx
|
69 | 69 | #endif
|
70 | 70 |
|
| 71 | +#include "spandsp/godard.h" |
71 | 72 | #include "spandsp/v29rx.h"
|
72 | 73 | #include "spandsp/v17tx.h"
|
73 | 74 | #include "spandsp/v17rx.h"
|
74 | 75 |
|
75 | 76 | #include "spandsp/private/logging.h"
|
76 | 77 | #include "spandsp/private/power_meter.h"
|
| 78 | +#include "spandsp/private/godard.h" |
77 | 79 | #include "spandsp/private/v17rx.h"
|
78 | 80 |
|
79 | 81 | #if defined(SPANDSP_USE_FIXED_POINTx)
|
|
101 | 103 | #include "v17_v32bis_rx_rrc.h"
|
102 | 104 | #include "v17_v32bis_tx_constellation_maps.h"
|
103 | 105 | #include "v17_v32bis_rx_constellation_maps.h"
|
| 106 | +#include "v17_v32bis_rx_godard.h" |
104 | 107 |
|
105 | 108 | /*! The nominal frequency of the carrier, in Hertz */
|
106 | 109 | #define CARRIER_NOMINAL_FREQ 1800.0f
|
|
128 | 131 | /*! The 16 bit pattern used in the bridge section of the training sequence */
|
129 | 132 | #define V17_BRIDGE_WORD 0x8880
|
130 | 133 |
|
131 |
| -/* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */ |
132 |
| -/* low_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ - BAUD_RATE/2.0f)/SAMPLE_RATE; */ |
133 |
| -/* high_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ + BAUD_RATE/2.0f)/SAMPLE_RATE; */ |
134 |
| -#define SIN_LOW_BAND_EDGE 0.453990499f |
135 |
| -#define COS_LOW_BAND_EDGE 0.891006542f |
136 |
| -#define SIN_HIGH_BAND_EDGE 0.707106781f |
137 |
| -#define COS_HIGH_BAND_EDGE -0.707106781f |
138 |
| -#define ALPHA 0.99f |
139 |
| - |
140 |
| -#define SYNC_LOW_BAND_EDGE_COEFF_0 FP_SYNC_SCALE(2.0f*ALPHA*COS_LOW_BAND_EDGE) |
141 |
| -#define SYNC_LOW_BAND_EDGE_COEFF_1 FP_SYNC_SCALE(-ALPHA*ALPHA) |
142 |
| -#define SYNC_LOW_BAND_EDGE_COEFF_2 FP_SYNC_SCALE(-ALPHA*SIN_LOW_BAND_EDGE) |
143 |
| -#define SYNC_HIGH_BAND_EDGE_COEFF_0 FP_SYNC_SCALE(2.0f*ALPHA*COS_HIGH_BAND_EDGE) |
144 |
| -#define SYNC_HIGH_BAND_EDGE_COEFF_1 FP_SYNC_SCALE(-ALPHA*ALPHA) |
145 |
| -#define SYNC_HIGH_BAND_EDGE_COEFF_2 FP_SYNC_SCALE(-ALPHA*SIN_HIGH_BAND_EDGE) |
146 |
| -#define SYNC_MIXED_EDGES_COEFF_3 FP_SYNC_SCALE(-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE)) |
147 |
| - |
148 | 134 | enum
|
149 | 135 | {
|
150 | 136 | TRAINING_STAGE_NORMAL_OPERATION = 0,
|
@@ -182,7 +168,7 @@ SPAN_DECLARE(float) v17_rx_carrier_frequency(v17_rx_state_t *s)
|
182 | 168 |
|
183 | 169 | SPAN_DECLARE(float) v17_rx_symbol_timing_correction(v17_rx_state_t *s)
|
184 | 170 | {
|
185 |
| - return (float) s->total_baud_timing_correction/((float) RX_PULSESHAPER_COEFF_SETS*10.0f/3.0f); |
| 171 | + return (float) godard_ted_correction(&s->godard)/((float) RX_PULSESHAPER_COEFF_SETS*10.0f/3.0f); |
186 | 172 | }
|
187 | 173 | /*- End of function --------------------------------------------------------*/
|
188 | 174 |
|
@@ -603,65 +589,6 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
|
603 | 589 | }
|
604 | 590 | /*- End of function --------------------------------------------------------*/
|
605 | 591 |
|
606 |
| -static __inline__ void symbol_sync(v17_rx_state_t *s) |
607 |
| -{ |
608 |
| - int i; |
609 |
| -#if defined(SPANDSP_USE_FIXED_POINTx) |
610 |
| - int32_t v; |
611 |
| - int32_t p; |
612 |
| -#else |
613 |
| - float v; |
614 |
| - float p; |
615 |
| -#endif |
616 |
| - |
617 |
| - /* This routine adapts the position of the half baud samples entering the equalizer. */ |
618 |
| - |
619 |
| - /* This symbol sync scheme is based on the technique first described by Dominique Godard in |
620 |
| - Passband Timing Recovery in an All-Digital Modem Receiver |
621 |
| - IEEE TRANSACTIONS ON COMMUNICATIONS, VOL. COM-26, NO. 5, MAY 1978 */ |
622 |
| - |
623 |
| - /* This is slightly rearranged from figure 3b of the Godard paper, as this saves a couple of |
624 |
| - maths operations */ |
625 |
| -#if defined(SPANDSP_USE_FIXED_POINTx) |
626 |
| - /* TODO: The scalings used here need more thorough evaluation, to see if overflows are possible. */ |
627 |
| - /* Cross correlate */ |
628 |
| - v = (((s->symbol_sync_low[1] >> (FP_SYNC_SHIFT_FACTOR/2))*(s->symbol_sync_high[0] >> (FP_SYNC_SHIFT_FACTOR/2))) >> 14)*SYNC_LOW_BAND_EDGE_COEFF_2 |
629 |
| - - (((s->symbol_sync_low[0] >> (FP_SYNC_SHIFT_FACTOR/2))*(s->symbol_sync_high[1] >> (FP_SYNC_SHIFT_FACTOR/2))) >> 14)*SYNC_HIGH_BAND_EDGE_COEFF_2 |
630 |
| - + (((s->symbol_sync_low[1] >> (FP_SYNC_SHIFT_FACTOR/2))*(s->symbol_sync_high[1] >> (FP_SYNC_SHIFT_FACTOR/2))) >> 14)*SYNC_MIXED_EDGES_COEFF_3; |
631 |
| - /* Filter away any DC component */ |
632 |
| - p = v - s->symbol_sync_dc_filter[1]; |
633 |
| - s->symbol_sync_dc_filter[1] = s->symbol_sync_dc_filter[0]; |
634 |
| - s->symbol_sync_dc_filter[0] = v; |
635 |
| - /* A little integration will now filter away much of the HF noise */ |
636 |
| - s->baud_phase -= p; |
637 |
| - v = labs(s->baud_phase); |
638 |
| -#else |
639 |
| - /* Cross correlate */ |
640 |
| - v = s->symbol_sync_low[1]*s->symbol_sync_high[0]*SYNC_LOW_BAND_EDGE_COEFF_2 |
641 |
| - - s->symbol_sync_low[0]*s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_2 |
642 |
| - + s->symbol_sync_low[1]*s->symbol_sync_high[1]*SYNC_MIXED_EDGES_COEFF_3; |
643 |
| - /* Filter away any DC component */ |
644 |
| - p = v - s->symbol_sync_dc_filter[1]; |
645 |
| - s->symbol_sync_dc_filter[1] = s->symbol_sync_dc_filter[0]; |
646 |
| - s->symbol_sync_dc_filter[0] = v; |
647 |
| - /* A little integration will now filter away much of the HF noise */ |
648 |
| - s->baud_phase -= p; |
649 |
| - v = fabsf(s->baud_phase); |
650 |
| -#endif |
651 |
| - if (v > FP_SYNC_SCALE_32(100.0f)) |
652 |
| - { |
653 |
| - i = (v > FP_SYNC_SCALE_32(1000.0f)) ? 15 : 1; |
654 |
| - if (s->baud_phase < FP_SYNC_SCALE_32(0.0f)) |
655 |
| - i = -i; |
656 |
| - /*endif*/ |
657 |
| - //printf("v = %10.5f %5d - %f %f %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction); |
658 |
| - s->eq_put_step += i; |
659 |
| - s->total_baud_timing_correction += i; |
660 |
| - } |
661 |
| - /*endif*/ |
662 |
| -} |
663 |
| -/*- End of function --------------------------------------------------------*/ |
664 |
| - |
665 | 592 | #if defined(SPANDSP_USE_FIXED_POINTx)
|
666 | 593 | static void process_half_baud(v17_rx_state_t *s, const complexi16_t *sample)
|
667 | 594 | #else
|
@@ -714,7 +641,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
714 | 641 | /*endif*/
|
715 | 642 |
|
716 | 643 | /* Symbol timing synchronisation */
|
717 |
| - symbol_sync(s); |
| 644 | + s->eq_put_step += godard_ted_per_baud(&s->godard); |
718 | 645 |
|
719 | 646 | z = equalizer_get(s);
|
720 | 647 |
|
@@ -1330,32 +1257,11 @@ SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
1330 | 1257 | #if defined(SPANDSP_USE_FIXED_POINTx)
|
1331 | 1258 | v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_re[step], V17_RX_FILTER_STEPS, s->rrc_filter_step) >> 15;
|
1332 | 1259 | sample.re = (v*s->agc_scaling) >> 10;
|
1333 |
| - /* Symbol timing synchronisation band edge filters */ |
1334 |
| - /* Low Nyquist band edge filter */ |
1335 |
| - v = ((s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0) >> FP_SYNC_SHIFT_FACTOR) |
1336 |
| - + ((s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1) >> FP_SYNC_SHIFT_FACTOR) |
1337 |
| - + sample.re; |
1338 |
| - s->symbol_sync_low[1] = s->symbol_sync_low[0]; |
1339 |
| - s->symbol_sync_low[0] = v; |
1340 |
| - /* High Nyquist band edge filter */ |
1341 |
| - v = ((s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0) >> FP_SYNC_SHIFT_FACTOR) |
1342 |
| - + ((s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1) >> FP_SYNC_SHIFT_FACTOR) |
1343 |
| - + sample.re; |
1344 |
| - s->symbol_sync_high[1] = s->symbol_sync_high[0]; |
1345 |
| - s->symbol_sync_high[0] = v; |
1346 | 1260 | #else
|
1347 | 1261 | v = vec_circular_dot_prodf(s->rrc_filter, rx_pulseshaper_re[step], V17_RX_FILTER_STEPS, s->rrc_filter_step);
|
1348 | 1262 | sample.re = v*s->agc_scaling;
|
1349 |
| - /* Symbol timing synchronisation band edge filters */ |
1350 |
| - /* Low Nyquist band edge filter */ |
1351 |
| - v = s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0 + s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1 + sample.re; |
1352 |
| - s->symbol_sync_low[1] = s->symbol_sync_low[0]; |
1353 |
| - s->symbol_sync_low[0] = v; |
1354 |
| - /* High Nyquist band edge filter */ |
1355 |
| - v = s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0 + s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1 + sample.re; |
1356 |
| - s->symbol_sync_high[1] = s->symbol_sync_high[0]; |
1357 |
| - s->symbol_sync_high[0] = v; |
1358 | 1263 | #endif
|
| 1264 | + godard_ted_rx(&s->godard, sample.re); |
1359 | 1265 | /* Put things into the equalization buffer at T/2 rate. The symbol synchronisation
|
1360 | 1266 | will fiddle the step to align this with the symbols. */
|
1361 | 1267 | if (s->eq_put_step <= 0)
|
@@ -1569,18 +1475,9 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
1569 | 1475 | span_log(&s->logging, SPAN_LOG_FLOW, "Gains %f %f\n", (float) s->agc_scaling_save, (float) s->agc_scaling);
|
1570 | 1476 | span_log(&s->logging, SPAN_LOG_FLOW, "Phase rates %f %f\n", dds_frequencyf(s->carrier_phase_rate), dds_frequencyf(s->carrier_phase_rate_save));
|
1571 | 1477 |
|
1572 |
| - /* Initialise the working data for symbol timing synchronisation */ |
1573 |
| - for (i = 0; i < 2; i++) |
1574 |
| - { |
1575 |
| - s->symbol_sync_low[i] = FP_SCALE(0.0f); |
1576 |
| - s->symbol_sync_high[i] = FP_SCALE(0.0f); |
1577 |
| - s->symbol_sync_dc_filter[i] = FP_SCALE(0.0f); |
1578 |
| - } |
1579 |
| - /*endfor*/ |
1580 |
| - s->baud_phase = FP_SCALE(0.0f); |
1581 |
| - s->baud_half = 0; |
| 1478 | + godard_ted_init(&s->godard, &godard_desc); |
1582 | 1479 |
|
1583 |
| - s->total_baud_timing_correction = 0; |
| 1480 | + s->baud_half = 0; |
1584 | 1481 |
|
1585 | 1482 | return 0;
|
1586 | 1483 | }
|
|
0 commit comments