30
30
*
31
31
* todo:
32
32
* sanity checks
33
- * scale squelch to other input parameters
34
33
* pad output on hop
35
34
* frequency ranges could be stored better
36
35
* auto-hop after time limit
@@ -124,10 +123,9 @@ struct dongle_state
124
123
125
124
struct agc_state
126
125
{
127
- int64_t gain_num ;
128
- int64_t gain_den ;
129
- int64_t gain_max ;
130
- int gain_int ;
126
+ int32_t gain_num ;
127
+ int32_t gain_den ;
128
+ int32_t gain_max ;
131
129
int peak_target ;
132
130
int attack_step ;
133
131
int decay_step ;
@@ -232,9 +230,9 @@ void usage(void)
232
230
"\t[-E enable_option (default: none)]\n"
233
231
"\t use multiple -E to enable multiple options\n"
234
232
"\t edge: enable lower edge tuning\n"
235
- "\t dc: enable dc blocking filter\n"
233
+ "\t no- dc: disable dc blocking filter\n"
236
234
"\t deemp: enable de-emphasis filter\n"
237
- "\t swagc: enable software agc (only for AM, broken )\n"
235
+ "\t swagc: enable software agc (only for AM modes )\n"
238
236
"\t direct: enable direct sampling\n"
239
237
"\t no-mod: enable no-mod direct sampling\n"
240
238
"\t offset: enable offset tuning\n"
@@ -633,7 +631,7 @@ void fm_demod(struct demod_state *fm)
633
631
void am_demod (struct demod_state * fm )
634
632
// todo, fix this extreme laziness
635
633
{
636
- int i , pcm ;
634
+ int32_t i , pcm ;
637
635
int16_t * lp = fm -> lowpassed ;
638
636
for (i = 0 ; i < fm -> lp_len ; i += 2 ) {
639
637
// hypot uses floats but won't overflow
@@ -643,7 +641,7 @@ void am_demod(struct demod_state *fm)
643
641
lp [i /2 ] = (int16_t )sqrt (pcm ) * fm -> output_scale ;
644
642
}
645
643
fm -> lp_len = fm -> lp_len / 2 ;
646
- // lowpass? (3khz) highpass? (dc)
644
+ // lowpass? (3khz)
647
645
}
648
646
649
647
void usb_demod (struct demod_state * fm )
@@ -764,29 +762,35 @@ int squelch_to_rms(int db, struct dongle_state *dongle, struct demod_state *demo
764
762
}
765
763
766
764
void software_agc (struct demod_state * d )
767
- /* ignores complex pairs, indirectly calculates power squelching */
768
765
{
769
766
int i = 0 ;
770
- int output ;
767
+ int peaked = 0 ;
768
+ int32_t output ;
771
769
struct agc_state * agc = d -> agc ;
772
770
int16_t * lp = d -> lowpassed ;
773
771
774
772
for (i = 0 ; i < d -> lp_len ; i ++ ) {
775
- output = (int )(( int64_t )lp [i ] * agc -> gain_num / agc -> gain_den );
773
+ output = (( int32_t )lp [i ] * agc -> gain_num / agc -> gain_den );
776
774
777
- if (abs (output ) < agc -> peak_target ) {
778
- agc -> gain_num += agc -> decay_step ;
775
+ if (!peaked && abs (output ) > agc -> peak_target ) {
776
+ peaked = 1 ;}
777
+ if (peaked ) {
778
+ agc -> gain_num += agc -> attack_step ;
779
779
} else {
780
- agc -> gain_num - = agc -> attack_step ;
780
+ agc -> gain_num + = agc -> decay_step ;
781
781
}
782
782
783
783
if (agc -> gain_num < agc -> gain_den ) {
784
784
agc -> gain_num = agc -> gain_den ;}
785
785
if (agc -> gain_num > agc -> gain_max ) {
786
786
agc -> gain_num = agc -> gain_max ;}
787
787
788
- agc -> gain_int = (int )(agc -> gain_num / agc -> gain_den );
789
- lp [i ] = output ;
788
+ if (output >= (1 <<15 )) {
789
+ output = (1 <<15 ) - 1 ;}
790
+ if (output < - (1 <<15 )) {
791
+ output = - (1 <<15 ) + 1 ;}
792
+
793
+ lp [i ] = (int16_t )output ;
790
794
}
791
795
}
792
796
@@ -812,12 +816,8 @@ void full_demod(struct demod_state *d)
812
816
} else {
813
817
low_pass (d );
814
818
}
815
- if (d -> agc_enable ) {
816
- software_agc (d );
817
- if (d -> squelch_level && d -> agc -> gain_int > d -> squelch_level ) {
818
- do_squelch = 1 ;}
819
819
/* power squelch */
820
- } else if (d -> squelch_level ) {
820
+ if (d -> squelch_level ) {
821
821
sr = rms (d -> lowpassed , d -> lp_len , 1 );
822
822
if (sr < d -> squelch_level ) {
823
823
do_squelch = 1 ;}
@@ -835,16 +835,17 @@ void full_demod(struct demod_state *d)
835
835
}
836
836
d -> mode_demod (d ); /* lowpassed -> lowpassed */
837
837
if (d -> mode_demod == & raw_demod ) {
838
- return ;
839
- }
838
+ return ;}
839
+ if (d -> dc_block ) {
840
+ dc_block_filter (d );}
841
+ if (d -> agc_enable ) {
842
+ software_agc (d );}
840
843
/* todo, fm noise squelch */
841
844
// use nicer filter here too?
842
845
if (d -> post_downsample > 1 ) {
843
846
d -> lp_len = low_pass_simple (d -> lowpassed , d -> lp_len , d -> post_downsample );}
844
847
if (d -> deemph ) {
845
848
deemph_filter (d );}
846
- if (d -> dc_block ) {
847
- dc_block_filter (d );}
848
849
if (d -> rate_out2 > 0 ) {
849
850
low_pass_real (d );
850
851
//arbitrary_resample(d->lowpassed, d->lowpassed, d->lp_len, d->lp_len * d->rate_out2 / d->rate_out);
@@ -1136,7 +1137,7 @@ void demod_init(struct demod_state *s)
1136
1137
s -> prev_lpr_index = 0 ;
1137
1138
s -> deemph_a = 0 ;
1138
1139
s -> now_lpr = 0 ;
1139
- s -> dc_block = 0 ;
1140
+ s -> dc_block = 1 ;
1140
1141
s -> dc_avg = 0 ;
1141
1142
pthread_rwlock_init (& s -> rw , NULL );
1142
1143
pthread_cond_init (& s -> ready , NULL );
@@ -1211,13 +1212,12 @@ int agc_init(struct demod_state *s)
1211
1212
agc = malloc (sizeof (struct agc_state ));
1212
1213
s -> agc = agc ;
1213
1214
1214
- agc -> gain_den = 1 <<13 ;
1215
+ agc -> gain_den = 1 <<16 ;
1215
1216
agc -> gain_num = agc -> gain_den ;
1216
- agc -> gain_int = (int )(agc -> gain_num / agc -> gain_den );
1217
- agc -> peak_target = 1 <<13 ;
1218
- agc -> gain_max = 1 <<10 * agc -> gain_num ;
1219
- agc -> attack_step = 2 ;
1217
+ agc -> peak_target = 1 <<14 ;
1218
+ agc -> gain_max = 256 * agc -> gain_den ;
1220
1219
agc -> decay_step = 1 ;
1220
+ agc -> attack_step = -2 ;
1221
1221
return 0 ;
1222
1222
}
1223
1223
@@ -1320,8 +1320,8 @@ int main(int argc, char **argv)
1320
1320
case 'E' :
1321
1321
if (strcmp ("edge" , optarg ) == 0 ) {
1322
1322
controller .edge = 1 ;}
1323
- if (strcmp ("dc" , optarg ) == 0 ) {
1324
- demod .dc_block = 1 ;}
1323
+ if (strcmp ("no- dc" , optarg ) == 0 ) {
1324
+ demod .dc_block = 0 ;}
1325
1325
if (strcmp ("deemp" , optarg ) == 0 ) {
1326
1326
demod .deemph = 1 ;}
1327
1327
if (strcmp ("swagc" , optarg ) == 0 ) {
0 commit comments