#!/usr/bin/env python # # Copyright 2004,2007,2010,2012,2013 Free Software Foundation, Inc. # # This file is part of GNU Radio # # SPDX-License-Identifier: GPL-3.0-or-later # # from gnuradio import gr, gr_unittest, analog, blocks class test_agc(gr_unittest.TestCase): def setUp(self): self.tb = gr.top_block() def tearDown(self): self.tb = None def test_001_sets(self): agc = analog.agc_cc(1e-3, 1, 1) agc.set_rate(1) agc.set_reference(1.1) agc.set_gain(1.1) agc.set_max_gain(100) self.assertAlmostEqual(agc.rate(), 1) self.assertAlmostEqual(agc.reference(), 1.1) self.assertAlmostEqual(agc.gain(), 1.1) self.assertAlmostEqual(agc.max_gain(), 100) def test_001(self): ''' Test the complex AGC loop (single rate input) ''' tb = self.tb expected_result = ( (100 + 0j), (72.89209747314453 + 52.9592170715332j), (25.089027404785156 + 77.2160873413086j), (-22.611034393310547 + 69.58960723876953j), (-53.35764694213867 + 38.766597747802734j), (-59.4586067199707 - 2.7399494229030097e-06j), (-43.3734245300293 - 31.51263999938965j), (-14.941386222839355 - 45.984867095947266j), (13.478157997131348 - 41.48149490356445j), (31.838510513305664 - 23.13202476501465j), (35.51927947998047 + 3.3255341804760974e-06j), (25.94291114807129 + 18.848634719848633j), (8.949296951293945 + 27.543113708496094j), (-8.085277557373047 + 24.883914947509766j), (-19.13165283203125 + 13.899954795837402j), (-21.383323669433594 - 2.987417019539862e-06j), (-15.65035343170166 - 11.370650291442871j), (-5.4110236167907715 - 16.653427124023438j), (4.900828838348389 - 15.083191871643066j), (11.62836742401123 - 8.448498725891113j), (13.036169052124023 + 2.4410530841123546e-06j), (9.572690963745117 + 6.954970359802246j), (3.3217051029205322 + 10.223164558410645j), (-3.0204410552978516 + 9.295955657958984j), (-7.197745323181152 + 5.229465007781982j), (-8.107251167297363 - 1.8916969111160142e-06j), (-5.983887195587158 - 4.347550392150879j), (-2.087981939315796 - 6.426152229309082j), (1.9100888967514038 - 5.87864351272583j), (4.581503391265869 - 3.3286550045013428j), (5.196768760681152 + 1.4596606661143596e-06j), (3.864729881286621 + 2.807892322540283j), (1.359479308128357 + 4.184051513671875j), (-1.2544355392456055 + 3.8607518672943115j), (-3.036635398864746 + 2.2062432765960693j), (-3.4781548976898193 - 1.137218077928992e-06j), (-2.613386869430542 - 1.8987380266189575j), (-0.9293051958084106 - 2.8601105213165283j), (0.8672783374786377 - 2.6692051887512207j), (2.1244049072265625 - 1.5434693098068237j), (2.463329315185547 + 9.225283861269418e-07j), (1.8744803667068481 + 1.3618910312652588j), (0.6752913594245911 + 2.078335762023926j), (-0.6386655569076538 + 1.9656078815460205j), (-1.5857415199279785 + 1.1521075963974j), (-1.864084243774414 - 7.840082503207668e-07j), (-1.438162922859192 - 1.0448874235153198j), (-0.5252984762191772 - 1.6167048215866089j), (0.5036717653274536 - 1.5501397848129272j), (1.2676655054092407 - 0.9210119843482971j)) sampling_freq = 100 src1 = analog.sig_source_c(sampling_freq, analog.GR_SIN_WAVE, sampling_freq * 0.10, 100.0) dst1 = blocks.vector_sink_c() head = blocks.head(gr.sizeof_gr_complex, int(5 * sampling_freq * 0.10)) agc = analog.agc_cc(1e-3, 1, 1) tb.connect(src1, head) tb.connect(head, agc) tb.connect(agc, dst1) tb.run() dst_data = dst1.data() self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 4) def test_002_sets(self): agc = analog.agc_ff(1e-3, 1, 1) agc.set_rate(1) agc.set_reference(1.1) agc.set_gain(1.1) agc.set_max_gain(100) self.assertAlmostEqual(agc.rate(), 1) self.assertAlmostEqual(agc.reference(), 1.1) self.assertAlmostEqual(agc.gain(), 1.1) self.assertAlmostEqual(agc.max_gain(), 100) def test_002(self): ''' Test the floating point AGC loop (single rate input) ''' tb = self.tb expected_result = ( 0.0, 58.83704376220703, 89.69985961914062, 81.26403045654297, 45.50606918334961, -3.3625440210016677e-06, -42.9488639831543, -65.50326538085938, -59.368656158447266, -33.26097869873047, 4.995997642254224e-06, 31.423521041870117, 47.950958251953125, 43.48566436767578, 24.37834358215332, -5.4677821026416495e-06, -23.06298828125, -35.21844482421875, -31.964082717895508, -17.93484115600586, 5.396469077822985e-06, 16.998228073120117, 25.982229232788086, 23.60628318786621, 13.260700225830078, -4.97806149724056e-06, -12.598825454711914, -19.282241821289062, -17.543500900268555, -9.870061874389648, 4.467380676942412e-06, 9.407480239868164, 14.422045707702637, 13.14553451538086, 7.410478591918945, -3.91256025977782e-06, -7.092466354370117, -10.896439552307129, -9.955231666564941, -5.62628698348999, 3.411524403418298e-06, 5.413146018981934, 8.338950157165527, 7.640974521636963, 4.332027435302734, -2.95963241114805e-06, -4.19495964050293, -6.483736991882324, -5.962202072143555, -3.3931667804718018) sampling_freq = 100 src1 = analog.sig_source_f(sampling_freq, analog.GR_SIN_WAVE, sampling_freq * 0.10, 100.0) dst1 = blocks.vector_sink_f() head = blocks.head(gr.sizeof_float, int(5 * sampling_freq * 0.10)) agc = analog.agc_ff(1e-3, 1, 1) tb.connect(src1, head) tb.connect(head, agc) tb.connect(agc, dst1) tb.run() dst_data = dst1.data() self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 4) def test_003_sets(self): agc = analog.agc2_cc(1e-3, 1e-1, 1, 1) agc.set_attack_rate(1) agc.set_decay_rate(2) agc.set_reference(1.1) agc.set_gain(1.1) agc.set_max_gain(100) self.assertAlmostEqual(agc.attack_rate(), 1) self.assertAlmostEqual(agc.decay_rate(), 2) self.assertAlmostEqual(agc.reference(), 1.1) self.assertAlmostEqual(agc.gain(), 1.1) self.assertAlmostEqual(agc.max_gain(), 100) def test_003(self): ''' Test the complex AGC loop (attack and decay rate inputs) ''' tb = self.tb expected_result = \ ((100 + 0j), (0.8090173602104187 + 0.5877856016159058j), (0.3090175688266754 + 0.9510582685470581j), (-0.309017539024353 + 0.9510582089424133j), (-0.8090170621871948 + 0.5877852439880371j), (-1.000004529953003 - 4.608183701293456e-08j), (-0.8090165853500366 - 0.587785005569458j), (-0.3090173006057739 - 0.9510576725006104j), (0.3090173900127411 - 0.951057493686676j), (0.8090166449546814 - 0.5877848863601685j), (1.0000040531158447 + 9.362654651567937e-08j), (0.809016227722168 + 0.5877848267555237j), (0.3090171217918396 + 0.9510573148727417j), (-0.3090173006057739 + 0.9510571360588074j), (-0.8090163469314575 + 0.5877846479415894j), (-1.000003695487976 - 1.39708305368913e-07j), (-0.8090159296989441 - 0.5877846479415894j), (-0.30901697278022766 - 0.951056957244873j), (0.30901727080345154 - 0.9510568976402283j), (0.809016227722168 - 0.5877844095230103j), (1.000003457069397 + 1.87252979344521e-07j), (0.809015691280365 + 0.5877845287322998j), (0.3090168535709381 + 0.9510567784309387j), (-0.30901727080345154 + 0.951056718826294j), (-0.8090161085128784 + 0.5877842903137207j), (-1.0000033378601074 - 2.3333473109232727e-07j), (-0.8090156316757202 - 0.5877845287322998j), (-0.3090168237686157 - 0.9510566592216492j), (0.3090173006057739 - 0.9510565400123596j), (0.8090160489082336 - 0.5877842307090759j), (1.0000032186508179 + 2.8087941927879e-07j), (0.8090155124664307 + 0.5877845287322998j), (0.30901676416397095 + 0.9510567784309387j), (-0.3090173006057739 + 0.9510565400123596j), (-0.8090160489082336 + 0.5877841711044312j), (-1.0000033378601074 - 3.2696124208086985e-07j), (-0.8090155124664307 - 0.5877845883369446j), (-0.30901673436164856 - 0.9510567784309387j), (0.3090173602104187 - 0.9510565400123596j), (0.8090160489082336 - 0.5877841114997864j), (1.0000033378601074 + 3.745059302673326e-07j), (0.8090154528617859 + 0.5877846479415894j), (0.3090166747570038 + 0.9510567784309387j), (-0.3090174198150635 + 0.9510565400123596j), (-0.8090161681175232 + 0.5877841114997864j), (-1.0000032186508179 - 4.2058766780428414e-07j), (-0.8090154528617859 - 0.5877846479415894j), (-0.309016615152359 - 0.9510567784309387j), (0.30901747941970825 - 0.9510564804077148j), (0.8090161681175232 - 0.5877840518951416j)) sampling_freq = 100 src1 = analog.sig_source_c(sampling_freq, analog.GR_SIN_WAVE, sampling_freq * 0.10, 100) dst1 = blocks.vector_sink_c() head = blocks.head(gr.sizeof_gr_complex, int(5 * sampling_freq * 0.10)) agc = analog.agc2_cc(1e-2, 1e-3, 1, 1) tb.connect(src1, head) tb.connect(head, agc) tb.connect(agc, dst1) tb.run() dst_data = dst1.data() self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 4) def test_004_sets(self): agc = analog.agc2_ff(1e-3, 1e-1, 1, 1) agc.set_attack_rate(1) agc.set_decay_rate(2) agc.set_reference(1.1) agc.set_gain(1.1) agc.set_max_gain(100) self.assertAlmostEqual(agc.attack_rate(), 1) self.assertAlmostEqual(agc.decay_rate(), 2) self.assertAlmostEqual(agc.reference(), 1.1) self.assertAlmostEqual(agc.gain(), 1.1) self.assertAlmostEqual(agc.max_gain(), 100) def test_004(self): ''' Test the floating point AGC loop (attack and decay rate inputs) ''' tb = self.tb expected_result = \ (0.0, 58.83704376220703, 40.194339752197266, 2.9184224605560303, 0.6760660409927368, -6.79303795436681e-08, -1.4542515277862549, -1.9210143089294434, -1.0450801849365234, -0.6193966865539551, 1.3429632872430375e-07, 1.4308913946151733, 1.9054334163665771, 1.044317603111267, 0.619373619556427, -2.003930177352231e-07, -1.4308818578720093, -1.905427098274231, -1.0443172454833984, -0.6193735599517822, 2.6858961632569844e-07, 1.4308820962905884, 1.9054267406463623, 1.0443172454833984, 0.6193734407424927, -3.3468785431978176e-07, -1.4308820962905884, -1.9054267406463623, -1.0443171262741089, -0.6193735599517822, 4.0288449554282124e-07, 1.430882215499878, 1.905427098274231, 1.0443170070648193, 0.6193734407424927, -4.689827903803234e-07, -1.430882453918457, -1.9054268598556519, -1.0443170070648193, -0.6193733811378479, 5.371793463382346e-07, 1.4308825731277466, 1.9054265022277832, 1.0443170070648193, 0.6193733811378479, -6.032776127540274e-07, -1.4308825731277466, -1.9054265022277832, -1.0443168878555298, -0.6193733811378479) sampling_freq = 100 src1 = analog.sig_source_f(sampling_freq, analog.GR_SIN_WAVE, sampling_freq * 0.10, 100) dst1 = blocks.vector_sink_f() head = blocks.head(gr.sizeof_float, int(5 * sampling_freq * 0.10)) agc = analog.agc2_ff(1e-2, 1e-3, 1, 1) tb.connect(src1, head) tb.connect(head, agc) tb.connect(agc, dst1) tb.run() dst_data = dst1.data() self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 4) def test_005(self): ''' Test the complex AGC loop (attack and decay rate inputs) ''' tb = self.tb expected_result = \ ((100 + 0j), (0.8090173602104187 + 0.5877856016159058j), (0.3090175688266754 + 0.9510582685470581j), (-0.309017539024353 + 0.9510582089424133j), (-0.8090170621871948 + 0.5877852439880371j), (-1.000004529953003 - 4.608183701293456e-08j), (-0.8090165853500366 - 0.587785005569458j), (-0.3090173006057739 - 0.9510576725006104j), (0.3090173900127411 - 0.951057493686676j), (0.8090166449546814 - 0.5877848863601685j), (1.0000040531158447 + 9.362654651567937e-08j), (0.809016227722168 + 0.5877848267555237j), (0.3090171217918396 + 0.9510573148727417j), (-0.3090173006057739 + 0.9510571360588074j), (-0.8090163469314575 + 0.5877846479415894j), (-1.000003695487976 - 1.39708305368913e-07j), (-0.8090159296989441 - 0.5877846479415894j), (-0.30901697278022766 - 0.951056957244873j), (0.30901727080345154 - 0.9510568976402283j), (0.809016227722168 - 0.5877844095230103j), (1.000003457069397 + 1.87252979344521e-07j), (0.809015691280365 + 0.5877845287322998j), (0.3090168535709381 + 0.9510567784309387j), (-0.30901727080345154 + 0.951056718826294j), (-0.8090161085128784 + 0.5877842903137207j), (-1.0000033378601074 - 2.3333473109232727e-07j), (-0.8090156316757202 - 0.5877845287322998j), (-0.3090168237686157 - 0.9510566592216492j), (0.3090173006057739 - 0.9510565400123596j), (0.8090160489082336 - 0.5877842307090759j), (1.0000032186508179 + 2.8087941927879e-07j), (0.8090155124664307 + 0.5877845287322998j), (0.30901676416397095 + 0.9510567784309387j), (-0.3090173006057739 + 0.9510565400123596j), (-0.8090160489082336 + 0.5877841711044312j), (-1.0000033378601074 - 3.2696124208086985e-07j), (-0.8090155124664307 - 0.5877845883369446j), (-0.30901673436164856 - 0.9510567784309387j), (0.3090173602104187 - 0.9510565400123596j), (0.8090160489082336 - 0.5877841114997864j), (1.0000033378601074 + 3.745059302673326e-07j), (0.8090154528617859 + 0.5877846479415894j), (0.3090166747570038 + 0.9510567784309387j), (-0.3090174198150635 + 0.9510565400123596j), (-0.8090161681175232 + 0.5877841114997864j), (-1.0000032186508179 - 4.2058766780428414e-07j), (-0.8090154528617859 - 0.5877846479415894j), (-0.309016615152359 - 0.9510567784309387j), (0.30901747941970825 - 0.9510564804077148j), (0.8090161681175232 - 0.5877840518951416j)) sampling_freq = 100 src1 = analog.sig_source_c(sampling_freq, analog.GR_SIN_WAVE, sampling_freq * 0.10, 100) dst1 = blocks.vector_sink_c() head = blocks.head(gr.sizeof_gr_complex, int(5 * sampling_freq * 0.10)) agc = analog.agc2_cc(1e-2, 1e-3, 1, 1) tb.connect(src1, head) tb.connect(head, agc) tb.connect(agc, dst1) tb.run() dst_data = dst1.data() self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 4) def test_006_sets(self): agc = analog.agc3_cc(1e-3, 1e-1, 1) agc.set_attack_rate(1) agc.set_decay_rate(2) agc.set_reference(1.1) agc.set_gain(1.1) self.assertAlmostEqual(agc.attack_rate(), 1) self.assertAlmostEqual(agc.decay_rate(), 2) self.assertAlmostEqual(agc.reference(), 1.1) self.assertAlmostEqual(agc.gain(), 1.1) def test_006(self): ''' Test the complex AGC loop (attack and decay rate inputs) ''' tb = self.tb sampling_freq = 100 # N must by a multiple of the volk_alignment of the system for this test to work. # For a machine with 512-bit registers, that would be 8 complex-floats. N = int(8 * sampling_freq) src1 = analog.sig_source_c(sampling_freq, analog.GR_SIN_WAVE, sampling_freq * 0.10, 100) dst1 = blocks.vector_sink_c() head = blocks.head(gr.sizeof_gr_complex, N) ref = 1 agc = analog.agc3_cc(1e-2, 1e-3, ref) tb.connect(src1, head) tb.connect(head, agc) tb.connect(agc, dst1) tb.run() dst_data = dst1.data() M = 100 result = [abs(x) for x in dst_data[N - M:]] self.assertFloatTuplesAlmostEqual(result, M * [ref, ], 4) def test_100(self): ''' Test complex feedforward agc with constant input ''' length = 8 gain = 2 input_data = 8 * (0.0,) + 24 * (1.0,) + 24 * (0.0,) expected_result = (8 + length - 1) * (0.0,) + 24 * (gain * 1.0,) + (0,) src = blocks.vector_source_c(input_data) agc = analog.feedforward_agc_cc(8, 2.0) dst = blocks.vector_sink_c() self.tb.connect(src, agc, dst) self.tb.run() dst_data = dst.data()[0:len(expected_result)] self.assertComplexTuplesAlmostEqual(expected_result, dst_data, 4) if __name__ == '__main__': gr_unittest.run(test_agc)