Vasil Velichkov | 2479152 | 2018-05-08 03:41:48 +0300 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # -*- coding: utf-8 -*- |
| 3 | # @file |
| 4 | # @author (C) 2018 by Vasil Velichkov <vvvelichkov@gmail.com> |
| 5 | # @section LICENSE |
| 6 | # |
| 7 | # Gr-gsm is free software; you can redistribute it and/or modify |
| 8 | # it under the terms of the GNU General Public License as published by |
| 9 | # the Free Software Foundation; either version 3, or (at your option) |
| 10 | # any later version. |
| 11 | # |
| 12 | # Gr-gsm is distributed in the hope that it will be useful, |
| 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | # GNU General Public License for more details. |
| 16 | # |
| 17 | # You should have received a copy of the GNU General Public License |
| 18 | # along with gr-gsm; see the file COPYING. If not, write to |
| 19 | # the Free Software Foundation, Inc., 51 Franklin Street, |
| 20 | # Boston, MA 02110-1301, USA. |
| 21 | # |
| 22 | # |
| 23 | |
| 24 | import numpy as np |
| 25 | from gnuradio import gr, gr_unittest, blocks |
| 26 | import grgsm_swig as grgsm |
| 27 | import pmt |
| 28 | |
| 29 | class qa_tch_h_decoder (gr_unittest.TestCase): |
| 30 | |
| 31 | def setUp (self): |
| 32 | self.tb = gr.top_block () |
| 33 | self.b = [ |
| 34 | "0001010001011010010000111100010101011011110000001011100101110010011101011000001001110100100010011111111000001001011000001100100010001011011000010000", |
| 35 | "0000000110100000010101000111011101101100010000101101000011000010011101011000001001110100001111000111000010100010111111011000001010111101110001000000", |
| 36 | "0000001101101000100100101101000011110011010110111100110000100010011101011000001001110100001110011100011000010000000111110100111110001101101100100000", |
| 37 | "0000011111010101110111001101111001001111010010000011111111010010011101011000001001110100010110000010000000000011100101111111010101111101111011101000", |
| 38 | "0001001110111000101001110001010011001101101111000010111100010010011101011000001001110100111000111011000111111100001011011011111001011100110111001000", |
| 39 | "0000110110000101000011001001011110110110001110001000010001000010011101011000001001110100000010100001010001011000000110001110011110001000111100110000", |
| 40 | "0000001101100010101011110100000010110100111110010010001100010010011101011000001001110100100000110001101011011101011110000110100010111100101011011000", |
| 41 | "0001111110100000011111010011100100001101011101000011011000000010011101011000001001110100100111110010000011100011000011001110001111110000001010011000", |
| 42 | "0001010100101010111010111001000100010100000010101011010011011010011101011000001001110100010100011100101110101110000000000111101011111111100011000000", |
| 43 | "0000000011011011101011000101000001001110001011101000100001011010011101011000001001110100000100011110101010100011010101010100101011101010000100000000", |
| 44 | "0001010110101001110001111001110100011010000110100000111001110010011101011000001001110100100100010101000100001100100000111111000001010111100011000000", |
| 45 | "0001100000100001100001100101101001101110001000101011100001010010011101011000001001110100110010110101000100100011011101111100000011100010000100000000", |
| 46 | "0001010110100000010010111001000100011110101010100001010001110010011101011000001001110100110100010100000110001100000000100111000011011111100011000000", |
| 47 | "0000101001110011000001000101001001101110001001100000100001110010011101011000001001110100100110110100001000100011111101111110101011100000100100000000", |
| 48 | |
| 49 | #FACCH framces 14 - 21 |
| 50 | "0001011000000010000000001000010111001000101111010000000010110010011101011000001001110101100000100000010010100000101000011000100011100010100000110000", |
| 51 | "0000010101111010111010000001100001110101111100001010101001100010011101011000001001110101111101111101101110000010110011111111110101010000001000110000", |
| 52 | "0000000000111110101010100001000000001000101110100010100100011010011101011000001001110101001010101011101010100000010100000000101111101000000000010000", |
| 53 | "0000001010010101011111011011101010101000000001011111111110101010011101011000001001110101101000010000010101111011111010100001010001011101111010101000", |
| 54 | "0001010100101010111010111001000100010100000010101011010011011010011101011000001001110100010100011100101110101110000000000111101011111111100011000000", |
| 55 | "0000000011011011101011000101000001001110001011101000100001011010011101011000001001110100000100011110101010100011010101010100101011101010000100000000", |
| 56 | "0001010110101001110001111001110100011010000110100000111001110010011101011000001001110100100100010101000100001100100000111111000001010111100011000000", |
| 57 | "0001100000100001100001100101101001101110001000101011100001010010011101011000001001110100110010110101000100100011011101111100000011100010000100000000", |
| 58 | ] |
| 59 | |
| 60 | def tearDown (self): |
| 61 | self.tb = None |
| 62 | |
| 63 | def tchh_multirate (self, frames, timeslots, bursts, multirate, subchan): |
| 64 | """ |
| 65 | Common TCH/H MultiRate test code |
| 66 | """ |
| 67 | src = grgsm.burst_source(frames, timeslots, bursts) |
| 68 | decoder = grgsm.tch_h_decoder(subchan, multirate, False); |
| 69 | dst = blocks.message_debug() |
| 70 | |
| 71 | self.tb.msg_connect(src, "out", decoder, "bursts") |
| 72 | self.tb.msg_connect(decoder, "voice", dst, "store") |
| 73 | |
| 74 | self.tb.run () |
| 75 | |
| 76 | result = [] |
| 77 | for i in range(0, dst.num_messages()): |
| 78 | pdu = dst.get_message(i) |
| 79 | self.assertEqual(True, pmt.is_pair(pdu)) |
| 80 | data = pmt.cdr(pdu) |
| 81 | self.assertEqual(True, pmt.is_blob(data)) |
| 82 | result.append(pmt.to_python(data).tolist()) |
| 83 | return result |
| 84 | |
| 85 | def test_amr7_40 (self): |
| 86 | """ |
| 87 | TCH/H MultiRate AMR 7.40 |
| 88 | """ |
| 89 | b = self.b |
| 90 | self.assertListEqual(self.tchh_multirate( |
| 91 | multirate = "28111a40", |
| 92 | subchan = 0, |
| 93 | frames = [259215, 259217, 259220, 259222, 259220, 259222, 259224, 259226], |
| 94 | timeslots = [ 6, 6, 6, 6, 6, 6, 6, 6], |
| 95 | bursts = [ b[8], b[9], b[10], b[11], b[10], b[11], b[12], b[13]]), |
| 96 | [ |
| 97 | [0x23,0x21,0x41,0x4d,0x52,0x0a], |
| 98 | [0x20,0xff,0x3c,0x67,0xe0,0x00,0x1f,0x3d,0x01,0xf0,0xfc,0x3f,0x77,0x18,0x61,0x86,0x00,0x00,0x00,0x00] |
| 99 | ]) |
| 100 | |
| 101 | def test_4_75 (self): |
| 102 | """ |
| 103 | TCH/H MultiRate AMR 4.75 |
| 104 | """ |
| 105 | b = self.b |
| 106 | self.assertListEqual(self.tchh_multirate( |
| 107 | multirate = "28111a40", |
| 108 | subchan = 0, |
| 109 | frames = [259666, 259668, 259670, 259672, 259670, 259672, 259675, 259677], |
| 110 | timeslots = [ 6, 6, 6, 6, 6, 6, 6, 6], |
| 111 | bursts = [ b[2], b[3], b[4], b[5], b[4], b[5], b[6], b[7]]), |
| 112 | [ |
| 113 | [0x23,0x21,0x41,0x4d,0x52,0x0a], |
| 114 | [0x00,0x67,0x19,0x24,0xd5,0x1b,0xd1,0x29,0x3f,0xa1,0x50,0x5f,0x3e] |
| 115 | ]) |
| 116 | |
| 117 | def test_amr7_40_and_4_75 (self): |
| 118 | """ |
| 119 | TCH/H MultiRate AMR 7.40 and 4.75 |
| 120 | Two 7.40 followed by two 4.75 frames |
| 121 | """ |
| 122 | b = self.b |
| 123 | self.assertListEqual(self.tchh_multirate( |
| 124 | multirate= "28111a40", |
| 125 | subchan = 0, |
| 126 | frames = [259657, 259659, 259662, 259664, |
| 127 | 259662, 259664, 259666, 259668, |
| 128 | 259666, 259668, 259670, 259672, |
| 129 | 259670, 259672, 259675, 259677, |
| 130 | 259675, 259677, 259679, 259681], |
| 131 | timeslots= [ 6, 6, 6, 6, |
| 132 | 6, 6, 6, 6, |
| 133 | 6, 6, 6, 6, |
| 134 | 6, 6, 6, 6, |
| 135 | 6, 6, 6, 6], |
| 136 | bursts = [ b[0], b[1], b[2], b[3], |
| 137 | b[0], b[1], b[2], b[3], |
| 138 | b[2], b[3], b[4], b[5], |
| 139 | b[2], b[3], b[4], b[5], |
| 140 | b[4], b[5], b[6], b[7]]), |
| 141 | [ |
| 142 | [0x23,0x21,0x41,0x4d,0x52,0x0a], |
| 143 | [0x20,0xe0,0x27,0x2a,0x00,0x21,0x30,0x38,0x75,0xf8,0x14,0x3c,0xec,0xde,0x0b,0x47,0x6f,0x9c,0xc6,0x70], |
| 144 | [0x20,0xe0,0x27,0x2a,0x00,0x21,0x30,0x38,0x75,0xf8,0x14,0x3c,0xec,0xde,0x0b,0x47,0x6f,0x9c,0xc6,0x70], |
| 145 | [0x00,0x67,0x19,0x24,0xd5,0x1b,0xd1,0x29,0x3f,0xa1,0x50,0x5f,0x3e], |
| 146 | [0x00,0x67,0x19,0x24,0xd5,0x1b,0xd1,0x29,0x3f,0xa1,0x50,0x5f,0x3e], |
| 147 | ]) |
| 148 | |
| 149 | def facch_test (self, frames, timeslots, bursts): |
| 150 | ''' |
| 151 | Common FACCH/TH test code |
| 152 | ''' |
| 153 | src = grgsm.burst_source(frames, timeslots, bursts) |
| 154 | decoder = grgsm.tch_h_decoder(0, "28111a40", False); |
| 155 | dst = blocks.message_debug() |
| 156 | facch = grgsm.message_sink() |
| 157 | |
| 158 | self.tb.msg_connect(src, "out", decoder, "bursts") |
| 159 | self.tb.msg_connect(decoder, "voice", dst, "store") |
| 160 | self.tb.msg_connect(decoder, "msgs", facch, "in") |
| 161 | |
| 162 | self.tb.run () |
| 163 | |
| 164 | self.assertEqual(dst.num_messages(), 0) |
| 165 | return list(facch.get_messages()) |
| 166 | |
| 167 | def test_facch_th (self): |
| 168 | """ |
| 169 | FACCH/TH test |
| 170 | """ |
| 171 | b = self.b |
| 172 | self.assertEqual(self.facch_test( |
| 173 | frames= [259207, 259209, 259211, 259213, 259211, 259213, 259215, 259217], |
| 174 | timeslots = [ 6, 6, 6, 6, 6, 6, 6, 6], |
| 175 | bursts = [ b[14], b[15], b[16], b[17], b[16], b[17], b[18], b[19]]), |
| 176 | ['02 04 01 06 00 00 00 00 00 03 f4 8b 06 00 00 00 03 60 09 03 0f 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b']) |
| 177 | |
| 178 | def test_facch_th_error (self): |
| 179 | """ |
| 180 | FACCH/TH Error handling test |
| 181 | """ |
| 182 | b = self.b |
| 183 | self.assertEqual(self.facch_test( |
| 184 | frames= [259207, 259209, 259211, 259213, 259211, 259213, 259215, 259217], |
| 185 | timeslots = [ 6, 6, 6, 6, 6, 6, 6, 6], |
| 186 | bursts = [ b[16], b[17], b[18], b[19], b[18], b[19], b[20], b[21]]), |
| 187 | []) #Must return an empty array |
| 188 | |
| 189 | if __name__ == '__main__': |
| 190 | gr_unittest.run(qa_tch_h_decoder, "qa_tch_h_decoder.xml") |