From fa75c578512bdda18532b583b891d645b194187d Mon Sep 17 00:00:00 2001 From: stevie Date: Wed, 28 Jan 2009 04:50:25 +0000 Subject: [PATCH] Add msgq to op25_decoder_ff to permit passing of snapshots to UI. Change swabbing to use a bit decoding map, make argument types template parameters (so bvec/bit_vector can be interchanged). Use a bit_queue (deque) for the frame buffer, pass this to all data_unit constructors. Add plumbing to send snapshot to the UI. New voice_data_unit as result of re-factoring LDU1/LDU2. Re-factor op25_decoder_ff to use the bit_queue for correlation and frame header (and body - but that's ignored just now). git-svn-id: http://op25.osmocom.org/svn/trunk@135 65a5c917-d112-43f1-993d-58c26a4786be --- decoder/src/lib/Makefile.am | 1 + decoder/src/lib/abstract_data_unit.cc | 16 ++- decoder/src/lib/abstract_data_unit.h | 21 +++- decoder/src/lib/data_unit.cc | 4 +- decoder/src/lib/data_unit.h | 15 ++- decoder/src/lib/hdu.cc | 70 +++++++++++- decoder/src/lib/hdu.h | 18 ++- decoder/src/lib/imbe_decoder.h | 4 +- decoder/src/lib/ldu1.cc | 153 ++----------------------- decoder/src/lib/ldu1.h | 41 ++----- decoder/src/lib/ldu2.cc | 153 ++----------------------- decoder/src/lib/ldu2.h | 38 ++----- decoder/src/lib/op25.i | 4 +- decoder/src/lib/op25_decoder_ff.cc | 156 +++++++++++++++++--------- decoder/src/lib/op25_decoder_ff.h | 51 ++++++--- decoder/src/lib/pdu.cc | 10 +- decoder/src/lib/pdu.h | 9 +- decoder/src/lib/swab.h | 91 +++++---------- decoder/src/lib/tdu.cc | 10 +- decoder/src/lib/tdu.h | 9 +- decoder/src/lib/vc55_imbe_decoder.cc | 4 +- decoder/src/python/qa_op25.py | 3 +- python/usrp_p25_rx.py | 46 +++++--- samples/p25-plain-silence.dat.info | 10 +- 24 files changed, 399 insertions(+), 538 deletions(-) diff --git a/decoder/src/lib/Makefile.am b/decoder/src/lib/Makefile.am index 33b1303..6d56785 100644 --- a/decoder/src/lib/Makefile.am +++ b/decoder/src/lib/Makefile.am @@ -68,6 +68,7 @@ _op25_la_SOURCES = \ tdu.cc \ imbe_decoder.cc \ dummy_imbe_decoder.cc \ + voice_data_unit.cc \ op25.cc \ op25_decoder_ff.cc \ vc55_imbe_decoder.cc diff --git a/decoder/src/lib/abstract_data_unit.cc b/decoder/src/lib/abstract_data_unit.cc index f72095b..c409ad9 100644 --- a/decoder/src/lib/abstract_data_unit.cc +++ b/decoder/src/lib/abstract_data_unit.cc @@ -25,8 +25,10 @@ #include #include +#include #include #include +#include using namespace std; @@ -88,9 +90,17 @@ abstract_data_unit::is_complete() const return d_frame_body.size() >= frame_size_max(); } -abstract_data_unit::abstract_data_unit(const_bit_vector& frame_body) : - d_frame_body(frame_body) +std::string +abstract_data_unit::snapshot() const { + string empty; + return empty; +} + +abstract_data_unit::abstract_data_unit(const_bit_queue& frame_body) : + d_frame_body(frame_body.size()) +{ + copy(frame_body.begin(), frame_body.end(), d_frame_body.begin()); } void @@ -107,7 +117,7 @@ abstract_data_unit::decode_audio(const_bit_vector& frame_body, imbe_decoder& imb size_t abstract_data_unit::decode_body(const_bit_vector& frame_body, size_t msg_sz, uint8_t *msg) { - return swab(frame_body, 0, frame_body.size(), msg); + return extract(frame_body, 0, frame_body.size(), msg); } uint16_t diff --git a/decoder/src/lib/abstract_data_unit.h b/decoder/src/lib/abstract_data_unit.h index aaf6f38..ae663e7 100644 --- a/decoder/src/lib/abstract_data_unit.h +++ b/decoder/src/lib/abstract_data_unit.h @@ -25,6 +25,7 @@ #define INCLUDED_ABSTRACT_DATA_UNIT_H #include +#include #include /** @@ -79,14 +80,23 @@ public: */ virtual bool is_complete() const; + /** + * Return a snapshot of the key fields from this frame in a manner + * suitable for display by the UI. The string is encoded as a + * pickled Python dictionary. + * + * \return A string containing the fields to display. + */ + virtual std::string snapshot() const; + protected: /** * abstract_data_unit constructor. * - * \param frame_body A const_bit_vector representing the frame body. + * \param frame_body A const_bit_queue representing the frame body. */ - abstract_data_unit(const_bit_vector& frame_body); + abstract_data_unit(const_bit_queue& frame_body); /** * Applies error correction code to the specified bit_vector. @@ -116,6 +126,13 @@ protected: */ virtual size_t decode_body(const_bit_vector& frame_body, size_t msg_sz, uint8_t *msg); + /** + * Returns a string describing the Data Unit ID (DUID). + * + * \return A string identifying the DUID. + */ + virtual std::string duid_str() const = 0; + /** * Returns the expected size (in bits) of this data_unit. For * variable-length data this should return UINT16_MAX until the diff --git a/decoder/src/lib/data_unit.cc b/decoder/src/lib/data_unit.cc index 76773cb..354fed1 100644 --- a/decoder/src/lib/data_unit.cc +++ b/decoder/src/lib/data_unit.cc @@ -26,12 +26,12 @@ #include #include #include +#include #include data_unit_sptr -data_unit::make_data_unit(const_bit_vector& frame_body) +data_unit::make_data_unit(const_bit_queue& frame_body) { - // ToDo: check frame_body length is at least 64 bits long! data_unit_sptr d; uint8_t duid = extract(frame_body, 60, 64); switch(duid) { diff --git a/decoder/src/lib/data_unit.h b/decoder/src/lib/data_unit.h index f4469a2..c546581 100644 --- a/decoder/src/lib/data_unit.h +++ b/decoder/src/lib/data_unit.h @@ -31,6 +31,9 @@ #include #include +typedef std::deque bit_queue; +typedef const std::deque const_bit_queue; + typedef uint8_t dibit; typedef std::deque float_queue; @@ -51,7 +54,7 @@ public: * \param nid The network ID for this data_unit. * \return A (possibly null-valued) pointer to the data_unit. */ - static data_unit_sptr make_data_unit(const_bit_vector& frame_body); + static data_unit_sptr make_data_unit(const_bit_queue& frame_body); /** * data_unit (virtual) destructor. @@ -97,6 +100,16 @@ public: */ virtual bool is_complete() const = 0; + /** + * Return a snapshot of the key fields from this frame in a manner + * suitable for display by the UI. The string is encoded using the + * Python pickle format allowing for different fields to be + * returned. + * + * \return A string containing the fields to display. + */ + virtual std::string snapshot() const = 0; + protected: /** diff --git a/decoder/src/lib/hdu.cc b/decoder/src/lib/hdu.cc index 676cb4d..45268d5 100644 --- a/decoder/src/lib/hdu.cc +++ b/decoder/src/lib/hdu.cc @@ -25,7 +25,9 @@ #include #include -hdu::hdu(const_bit_vector& frame_body) : +using std::string; + +hdu::hdu(const_bit_queue& frame_body) : abstract_data_unit(frame_body) { } @@ -34,6 +36,19 @@ hdu::~hdu() { } +string +hdu::duid_str() const +{ + return string("HDU"); +} + +std::string +hdu::snapshot() const +{ + string empty; + return empty; +} + void hdu::correct_errors(bit_vector& frame) { @@ -44,14 +59,63 @@ hdu::correct_errors(bit_vector& frame) void hdu::apply_golay_correction(bit_vector& frame) { - // static itpp::Extended_Golay golay; + static itpp::Extended_Golay golay; + static const size_t nof_golay_codewords = 36, golay_codeword_sz = 18; + static const size_t golay_codewords[nof_golay_codewords][golay_codeword_sz] = { + { 119, 118, 117, 116, 115, 114, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120 }, + { 137, 136, 135, 134, 133, 132, 151, 150, 149, 148, 147, 146, 145, 144, 141, 140, 139, 138 }, + { 157, 156, 155, 154, 153, 152, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158 }, + { 175, 174, 173, 172, 171, 170, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176 }, + { 193, 192, 191, 190, 189, 188, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194 }, + { 211, 210, 209, 208, 207, 206, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 213, 212 }, + { 231, 230, 229, 228, 227, 226, 243, 242, 241, 240, 239, 238, 237, 236, 235, 234, 233, 232 }, + { 249, 248, 247, 246, 245, 244, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, 250 }, + { 267, 266, 265, 264, 263, 262, 279, 278, 277, 276, 275, 274, 273, 272, 271, 270, 269, 268 }, + { 285, 284, 283, 282, 281, 280, 299, 298, 297, 296, 295, 294, 293, 292, 291, 290, 289, 288 }, + { 305, 304, 303, 302, 301, 300, 317, 316, 315, 314, 313, 312, 311, 310, 309, 308, 307, 306 }, + { 323, 322, 321, 320, 319, 318, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, 324 }, + { 341, 340, 339, 338, 337, 336, 353, 352, 351, 350, 349, 348, 347, 346, 345, 344, 343, 342 }, + { 361, 360, 357, 356, 355, 354, 373, 372, 371, 370, 369, 368, 367, 366, 365, 364, 363, 362 }, + { 379, 378, 377, 376, 375, 374, 391, 390, 389, 388, 387, 386, 385, 384, 383, 382, 381, 380 }, + { 397, 396, 395, 394, 393, 392, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400, 399, 398 }, + { 415, 414, 413, 412, 411, 410, 427, 426, 425, 424, 423, 422, 421, 420, 419, 418, 417, 416 }, + { 435, 434, 433, 432, 429, 428, 447, 446, 445, 444, 443, 442, 441, 440, 439, 438, 437, 436 }, + { 453, 452, 451, 450, 449, 448, 465, 464, 463, 462, 461, 460, 459, 458, 457, 456, 455, 454 }, + { 471, 470, 469, 468, 467, 466, 483, 482, 481, 480, 479, 478, 477, 476, 475, 474, 473, 472 }, + { 489, 488, 487, 486, 485, 484, 501, 500, 499, 498, 497, 496, 495, 494, 493, 492, 491, 490 }, + { 509, 508, 507, 506, 505, 504, 521, 520, 519, 518, 517, 516, 515, 514, 513, 512, 511, 510 }, + { 527, 526, 525, 524, 523, 522, 539, 538, 537, 536, 535, 534, 533, 532, 531, 530, 529, 528 }, + { 545, 544, 543, 542, 541, 540, 557, 556, 555, 554, 553, 552, 551, 550, 549, 548, 547, 546 }, + { 563, 562, 561, 560, 559, 558, 577, 576, 573, 572, 571, 570, 569, 568, 567, 566, 565, 564 }, + { 583, 582, 581, 580, 579, 578, 595, 594, 593, 592, 591, 590, 589, 588, 587, 586, 585, 584 }, + { 601, 600, 599, 598, 597, 596, 613, 612, 611, 610, 609, 608, 607, 606, 605, 604, 603, 602 }, + { 619, 618, 617, 616, 615, 614, 631, 630, 629, 628, 627, 626, 625, 624, 623, 622, 621, 620 }, + { 637, 636, 635, 634, 633, 632, 651, 650, 649, 648, 645, 644, 643, 642, 641, 640, 639, 638 }, + { 657, 656, 655, 654, 653, 652, 669, 668, 667, 666, 665, 664, 663, 662, 661, 660, 659, 658 }, + { 675, 674, 673, 672, 671, 670, 687, 686, 685, 684, 683, 682, 681, 680, 679, 678, 677, 676 }, + { 693, 692, 691, 690, 689, 688, 705, 704, 703, 702, 701, 700, 699, 698, 697, 696, 695, 694 }, + { 711, 710, 709, 708, 707, 706, 725, 724, 723, 722, 721, 720, 717, 716, 715, 714, 713, 712 }, + { 731, 730, 729, 728, 727, 726, 743, 742, 741, 740, 739, 738, 737, 736, 735, 734, 733, 732 }, + { 749, 748, 747, 746, 745, 744, 761, 760, 759, 758, 757, 756, 755, 754, 753, 752, 751, 750 }, + { 767, 766, 765, 764, 763, 762, 779, 778, 777, 776, 775, 774, 773, 772, 771, 770, 769, 768 } + }; + for(size_t i = 0; i < nof_golay_codewords; ++i) { + // ToDo: + } } void hdu::apply_rs_correction(bit_vector& frame) { - // static itpp::Reed_Solomon rs(63, 47, 17, true); + static itpp::Reed_Solomon rs(6, 8, true); + +#if 0 + const size_t rs_codeword[][6] = { + }; + const size_t nof_codeword_bits = sizeof(codeword_bits) / sizeof(codeword_bits[0]); + +#endif } uint16_t diff --git a/decoder/src/lib/hdu.h b/decoder/src/lib/hdu.h index 323d104..10e447d 100644 --- a/decoder/src/lib/hdu.h +++ b/decoder/src/lib/hdu.h @@ -37,15 +37,29 @@ public: /** * hdu constructor. * - * \param frame_body A const_bit_vector representing the frame body. + * \param frame_body A const_bit_queue representing the frame body. */ - hdu(const bit_vector& frame_body); + hdu(const_bit_queue& frame_body); /** * hdu virtual destructor. */ virtual ~hdu(); + /** + * Returns a string describing the Data Unit ID (DUID). + */ + std::string duid_str() const; + + /** + * Return a snapshot of the key fields from this frame in a manner + * suitable for display by the UI. The string is encoded as a + * pickled Python dictionary. + * + * \return A string containing the fields to display. + */ + virtual std::string snapshot() const; + protected: /** diff --git a/decoder/src/lib/imbe_decoder.h b/decoder/src/lib/imbe_decoder.h index e8e2329..ee8ee6a 100644 --- a/decoder/src/lib/imbe_decoder.h +++ b/decoder/src/lib/imbe_decoder.h @@ -24,13 +24,13 @@ #ifndef INCLUDED_IMBE_DECODER_H #define INCLUDED_IMBE_DECODER_H -#include #include #include #include +#include -typedef std::bitset<144> voice_codeword; typedef std::deque audio_output; +typedef std::vector voice_codeword; typedef boost::shared_ptr imbe_decoder_sptr; diff --git a/decoder/src/lib/ldu1.cc b/decoder/src/lib/ldu1.cc index 0de180d..19f9c2f 100644 --- a/decoder/src/lib/ldu1.cc +++ b/decoder/src/lib/ldu1.cc @@ -23,8 +23,10 @@ #include -ldu1::ldu1(const_bit_vector& frame_body) : - abstract_data_unit(frame_body) +using std::string; + +ldu1::ldu1(const_bit_queue& frame_body) : + voice_data_unit(frame_body) { } @@ -32,149 +34,8 @@ ldu1::~ldu1() { } -void -ldu1::correct_errors(bit_vector& frame_body) +string +ldu1::duid_str() const { -} - -size_t -ldu1::decode_audio(const_bit_vector& frame_body, imbe_decoder& imbe, float_queue& audio) -{ - static const size_t nof_voice_codewords = 9, voice_codeword_sz = 144; - static const size_t voice_codeword_bits[nof_voice_codewords][voice_codeword_sz] = { - - { 114, 121, 126, 133, 138, 147, 152, 159, 164, 171, 176, 183, - 188, 195, 200, 207, 212, 221, 226, 233, 238, 245, 250, 257, - 115, 120, 127, 132, 139, 146, 153, 158, 165, 170, 177, 182, - 189, 194, 201, 206, 213, 220, 227, 232, 239, 244, 251, 256, - 116, 123, 128, 135, 140, 149, 154, 161, 166, 173, 178, 185, - 190, 197, 202, 209, 216, 223, 228, 235, 240, 247, 252, 259, - 117, 122, 129, 134, 141, 148, 155, 160, 167, 172, 179, 184, - 191, 196, 203, 208, 217, 222, 229, 234, 241, 246, 253, 258, - 118, 125, 130, 137, 144, 151, 156, 163, 168, 175, 180, 187, - 192, 199, 204, 211, 218, 225, 230, 237, 242, 249, 254, 261, - 119, 124, 131, 136, 145, 150, 157, 162, 169, 174, 181, 186, - 193, 198, 205, 210, 219, 224, 231, 236, 243, 248, 255, 260 }, - - { 262, 269, 274, 281, 288, 295, 300, 307, 312, 319, 324, 331, - 336, 343, 348, 355, 362, 369, 374, 381, 386, 393, 398, 405, - 263, 268, 275, 280, 289, 294, 301, 306, 313, 318, 325, 330, - 337, 342, 349, 354, 363, 368, 375, 380, 387, 392, 399, 404, - 264, 271, 276, 283, 290, 297, 302, 309, 314, 321, 326, 333, - 338, 345, 350, 357, 364, 371, 376, 383, 388, 395, 400, 407, - 265, 270, 277, 282, 291, 296, 303, 308, 315, 320, 327, 332, - 339, 344, 351, 356, 365, 370, 377, 382, 389, 394, 401, 406, - 266, 273, 278, 285, 292, 299, 304, 311, 316, 323, 328, 335, - 340, 347, 352, 361, 366, 373, 378, 385, 390, 397, 402, 409, - 267, 272, 279, 284, 293, 298, 305, 310, 317, 322, 329, 334, - 341, 346, 353, 360, 367, 372, 379, 384, 391, 396, 403, 408 }, - - { 452, 459, 464, 471, 476, 483, 488, 495, 500, 509, 514, 521, - 526, 533, 538, 545, 550, 557, 562, 569, 576, 583, 588, 595, - 453, 458, 465, 470, 477, 482, 489, 494, 501, 508, 515, 520, - 527, 532, 539, 544, 551, 556, 563, 568, 577, 582, 589, 594, - 454, 461, 466, 473, 478, 485, 490, 497, 504, 511, 516, 523, - 528, 535, 540, 547, 552, 559, 564, 571, 578, 585, 590, 597, - 455, 460, 467, 472, 479, 484, 491, 496, 505, 510, 517, 522, - 529, 534, 541, 546, 553, 558, 565, 570, 579, 584, 591, 596, - 456, 463, 468, 475, 480, 487, 492, 499, 506, 513, 518, 525, - 530, 537, 542, 549, 554, 561, 566, 573, 580, 587, 592, 599, - 457, 462, 469, 474, 481, 486, 493, 498, 507, 512, 519, 524, - 531, 536, 543, 548, 555, 560, 567, 572, 581, 586, 593, 598 }, - - { 640, 649, 654, 661, 666, 673, 678, 685, 690, 697, 702, 709, - 714, 723, 728, 735, 740, 747, 752, 759, 764, 771, 776, 783, - 641, 648, 655, 660, 667, 672, 679, 684, 691, 696, 703, 708, - 715, 722, 729, 734, 741, 746, 753, 758, 765, 770, 777, 782, - 642, 651, 656, 663, 668, 675, 680, 687, 692, 699, 704, 711, - 716, 725, 730, 737, 742, 749, 754, 761, 766, 773, 778, 785, - 643, 650, 657, 662, 669, 674, 681, 686, 693, 698, 705, 710, - 717, 724, 731, 736, 743, 748, 755, 760, 767, 772, 779, 784, - 644, 653, 658, 665, 670, 677, 682, 689, 694, 701, 706, 713, - 720, 727, 732, 739, 744, 751, 756, 763, 768, 775, 780, 787, - 645, 652, 659, 664, 671, 676, 683, 688, 695, 700, 707, 712, - 721, 726, 733, 738, 745, 750, 757, 762, 769, 774, 781, 786 }, - - { 830, 837, 842, 849, 854, 861, 868, 875, 880, 887, 892, 899, - 904, 911, 916, 923, 928, 937, 942, 949, 954, 961, 966, 973, - 831, 836, 843, 848, 855, 860, 869, 874, 881, 886, 893, 898, - 905, 910, 917, 922, 929, 936, 943, 948, 955, 960, 967, 972, - 832, 839, 844, 851, 856, 865, 870, 877, 882, 889, 894, 901, - 906, 913, 918, 925, 930, 939, 944, 951, 956, 963, 968, 975, - 833, 838, 845, 850, 857, 864, 871, 876, 883, 888, 895, 900, - 907, 912, 919, 924, 931, 938, 945, 950, 957, 962, 969, 974, - 834, 841, 846, 853, 858, 867, 872, 879, 884, 891, 896, 903, - 908, 915, 920, 927, 932, 941, 946, 953, 958, 965, 970, 977, - 835, 840, 847, 852, 859, 866, 873, 878, 885, 890, 897, 902, - 909, 914, 921, 926, 933, 940, 947, 952, 959, 964, 971, 976 }, - - { 1020, 1027, 1032, 1039, 1044, 1051, 1056, 1063, 1068, 1075, 1082, 1089, - 1094, 1101, 1106, 1113, 1118, 1125, 1130, 1137, 1142, 1149, 1156, 1163, - 1021, 1026, 1033, 1038, 1045, 1050, 1057, 1062, 1069, 1074, 1083, 1088, - 1095, 1100, 1107, 1112, 1119, 1124, 1131, 1136, 1143, 1148, 1157, 1162, - 1022, 1029, 1034, 1041, 1046, 1053, 1058, 1065, 1070, 1077, 1084, 1091, - 1096, 1103, 1108, 1115, 1120, 1127, 1132, 1139, 1144, 1153, 1158, 1165, - 1023, 1028, 1035, 1040, 1047, 1052, 1059, 1064, 1071, 1076, 1085, 1090, - 1097, 1102, 1109, 1114, 1121, 1126, 1133, 1138, 1145, 1152, 1159, 1164, - 1024, 1031, 1036, 1043, 1048, 1055, 1060, 1067, 1072, 1081, 1086, 1093, - 1098, 1105, 1110, 1117, 1122, 1129, 1134, 1141, 1146, 1155, 1160, 1167, - 1025, 1030, 1037, 1042, 1049, 1054, 1061, 1066, 1073, 1080, 1087, 1092, - 1099, 1104, 1111, 1116, 1123, 1128, 1135, 1140, 1147, 1154, 1161, 1166 }, - - { 1208, 1215, 1220, 1229, 1234, 1241, 1246, 1253, 1258, 1265, 1270, 1277, - 1282, 1289, 1296, 1303, 1308, 1315, 1320, 1327, 1332, 1339, 1344, 1351, - 1209, 1214, 1221, 1228, 1235, 1240, 1247, 1252, 1259, 1264, 1271, 1276, - 1283, 1288, 1297, 1302, 1309, 1314, 1321, 1326, 1333, 1338, 1345, 1350, - 1210, 1217, 1224, 1231, 1236, 1243, 1248, 1255, 1260, 1267, 1272, 1279, - 1284, 1291, 1298, 1305, 1310, 1317, 1322, 1329, 1334, 1341, 1346, 1353, - 1211, 1216, 1225, 1230, 1237, 1242, 1249, 1254, 1261, 1266, 1273, 1278, - 1285, 1290, 1299, 1304, 1311, 1316, 1323, 1328, 1335, 1340, 1347, 1352, - 1212, 1219, 1226, 1233, 1238, 1245, 1250, 1257, 1262, 1269, 1274, 1281, - 1286, 1293, 1300, 1307, 1312, 1319, 1324, 1331, 1336, 1343, 1348, 1355, - 1213, 1218, 1227, 1232, 1239, 1244, 1251, 1256, 1263, 1268, 1275, 1280, - 1287, 1292, 1301, 1306, 1313, 1318, 1325, 1330, 1337, 1342, 1349, 1354 }, - - { 1398, 1405, 1410, 1417, 1422, 1429, 1434, 1443, 1448, 1455, 1460, 1467, - 1472, 1479, 1484, 1491, 1496, 1503, 1508, 1517, 1522, 1529, 1534, 1541, - 1399, 1404, 1411, 1416, 1423, 1428, 1435, 1442, 1449, 1454, 1461, 1466, - 1473, 1478, 1485, 1490, 1497, 1502, 1509, 1516, 1523, 1528, 1535, 1540, - 1400, 1407, 1412, 1419, 1424, 1431, 1436, 1445, 1450, 1457, 1462, 1469, - 1474, 1481, 1486, 1493, 1498, 1505, 1512, 1519, 1524, 1531, 1536, 1543, - 1401, 1406, 1413, 1418, 1425, 1430, 1437, 1444, 1451, 1456, 1463, 1468, - 1475, 1480, 1487, 1492, 1499, 1504, 1513, 1518, 1525, 1530, 1537, 1542, - 1402, 1409, 1414, 1421, 1426, 1433, 1440, 1447, 1452, 1459, 1464, 1471, - 1476, 1483, 1488, 1495, 1500, 1507, 1514, 1521, 1526, 1533, 1538, 1545, - 1403, 1408, 1415, 1420, 1427, 1432, 1441, 1446, 1453, 1458, 1465, 1470, - 1477, 1482, 1489, 1494, 1501, 1506, 1515, 1520, 1527, 1532, 1539, 1544 }, - - { 1578, 1587, 1592, 1599, 1604, 1611, 1616, 1623, 1628, 1635, 1640, 1647, - 1652, 1661, 1666, 1673, 1678, 1685, 1690, 1697, 1702, 1709, 1714, 1721, - 1579, 1586, 1593, 1598, 1605, 1610, 1617, 1622, 1629, 1634, 1641, 1646, - 1653, 1660, 1667, 1672, 1679, 1684, 1691, 1696, 1703, 1708, 1715, 1720, - 1580, 1589, 1594, 1601, 1606, 1613, 1618, 1625, 1630, 1637, 1642, 1649, - 1656, 1663, 1668, 1675, 1680, 1687, 1692, 1699, 1704, 1711, 1716, 1723, - 1581, 1588, 1595, 1600, 1607, 1612, 1619, 1624, 1631, 1636, 1643, 1648, - 1657, 1662, 1669, 1674, 1681, 1686, 1693, 1698, 1705, 1710, 1717, 1722, - 1584, 1591, 1596, 1603, 1608, 1615, 1620, 1627, 1632, 1639, 1644, 1651, - 1658, 1665, 1670, 1677, 1682, 1689, 1694, 1701, 1706, 1713, 1718, 1725, - 1585, 1590, 1597, 1602, 1609, 1614, 1621, 1626, 1633, 1638, 1645, 1650, - 1659, 1664, 1671, 1676, 1683, 1688, 1695, 1700, 1707, 1712, 1719, 1724 }, - - }; - - size_t nof_samples = 0; - for(size_t i = 0; i < nof_voice_codewords; ++i) { - voice_codeword cw; - for(size_t j = 0; j < voice_codeword_sz; ++j) { - cw[j] = frame_body[voice_codeword_bits[i][j]]; - } - nof_samples += imbe.decode(cw, audio); - } - return nof_samples; -} - -uint16_t -ldu1::frame_size_max() const -{ - return 1728; + return string("LDU1"); } diff --git a/decoder/src/lib/ldu1.h b/decoder/src/lib/ldu1.h index a50a765..b9feee8 100644 --- a/decoder/src/lib/ldu1.h +++ b/decoder/src/lib/ldu1.h @@ -24,58 +24,31 @@ #ifndef INCLUDED_LDU1_H #define INCLUDED_LDU1_H -#include +#include /** - * P25 Logical Data Unit 1 (compressed IBME voice). + * P25 Logical Data Unit 1. */ -class ldu1 : public abstract_data_unit +class ldu1 : public voice_data_unit { public: /** * ldu1 constuctor * - * \param frame_body A const_bit_vector representing the frame body. + * \param frame_body A const_bit_queue representing the frame body. */ - ldu1(const_bit_vector& frame_body); + ldu1(const_bit_queue& frame_body); /** * ldu1 (virtual) destuctor */ virtual ~ldu1(); -protected: - /** - * Applies error correction code to the specified bit_vector. Not - * that this function removes the PN sequences from the source - * frame. - * - * \param frame_body The bit vector to decode. - * \return + * Returns a string describing the Data Unit ID (DUID). */ - virtual void correct_errors(bit_vector& frame_body); - - /** - * Decode compressed audio using the supplied imbe_decoder and - * writes output to audio. - * - * \param frame_body The const_bit_vector to decode. - * \param imbe The imbe_decoder to use to generate the audio. - * \param audio A deque to which the audio (if any) is appended. - * \return The number of samples written to audio. - */ - virtual size_t decode_audio(const_bit_vector& frame_body, imbe_decoder& imbe, float_queue& audio); - - /** - * Returns the expected size (in bits) of this data_unit. For - * variable-length data this should return UINT16_MAX until the - * actual length of this frame is known. - * - * \return The expected size (in bits) of this data_unit when encoded. - */ - virtual uint16_t frame_size_max() const; + std::string duid_str() const; }; diff --git a/decoder/src/lib/ldu2.cc b/decoder/src/lib/ldu2.cc index befee35..8638275 100644 --- a/decoder/src/lib/ldu2.cc +++ b/decoder/src/lib/ldu2.cc @@ -23,8 +23,10 @@ #include -ldu2::ldu2(const_bit_vector& frame_body) : - abstract_data_unit(frame_body) +using std::string; + +ldu2::ldu2(const_bit_queue& frame_body) : + voice_data_unit(frame_body) { } @@ -32,149 +34,8 @@ ldu2::~ldu2() { } -void -ldu2::correct_errors(bit_vector& frame_body) +string +ldu2::duid_str() const { -} - -size_t -ldu2::decode_audio(const_bit_vector& frame_body, imbe_decoder& imbe, float_queue& audio) -{ - static const size_t nof_voice_codewords = 9, voice_codeword_sz = 144; - static const size_t voice_codeword_bits[nof_voice_codewords][voice_codeword_sz] = { - - { 114, 121, 126, 133, 138, 147, 152, 159, 164, 171, 176, 183, - 188, 195, 200, 207, 212, 221, 226, 233, 238, 245, 250, 257, - 115, 120, 127, 132, 139, 146, 153, 158, 165, 170, 177, 182, - 189, 194, 201, 206, 213, 220, 227, 232, 239, 244, 251, 256, - 116, 123, 128, 135, 140, 149, 154, 161, 166, 173, 178, 185, - 190, 197, 202, 209, 216, 223, 228, 235, 240, 247, 252, 259, - 117, 122, 129, 134, 141, 148, 155, 160, 167, 172, 179, 184, - 191, 196, 203, 208, 217, 222, 229, 234, 241, 246, 253, 258, - 118, 125, 130, 137, 144, 151, 156, 163, 168, 175, 180, 187, - 192, 199, 204, 211, 218, 225, 230, 237, 242, 249, 254, 261, - 119, 124, 131, 136, 145, 150, 157, 162, 169, 174, 181, 186, - 193, 198, 205, 210, 219, 224, 231, 236, 243, 248, 255, 260 }, - - { 262, 269, 274, 281, 288, 295, 300, 307, 312, 319, 324, 331, - 336, 343, 348, 355, 362, 369, 374, 381, 386, 393, 398, 405, - 263, 268, 275, 280, 289, 294, 301, 306, 313, 318, 325, 330, - 337, 342, 349, 354, 363, 368, 375, 380, 387, 392, 399, 404, - 264, 271, 276, 283, 290, 297, 302, 309, 314, 321, 326, 333, - 338, 345, 350, 357, 364, 371, 376, 383, 388, 395, 400, 407, - 265, 270, 277, 282, 291, 296, 303, 308, 315, 320, 327, 332, - 339, 344, 351, 356, 365, 370, 377, 382, 389, 394, 401, 406, - 266, 273, 278, 285, 292, 299, 304, 311, 316, 323, 328, 335, - 340, 347, 352, 361, 366, 373, 378, 385, 390, 397, 402, 409, - 267, 272, 279, 284, 293, 298, 305, 310, 317, 322, 329, 334, - 341, 346, 353, 360, 367, 372, 379, 384, 391, 396, 403, 408 }, - - { 452, 459, 464, 471, 476, 483, 488, 495, 500, 509, 514, 521, - 526, 533, 538, 545, 550, 557, 562, 569, 576, 583, 588, 595, - 453, 458, 465, 470, 477, 482, 489, 494, 501, 508, 515, 520, - 527, 532, 539, 544, 551, 556, 563, 568, 577, 582, 589, 594, - 454, 461, 466, 473, 478, 485, 490, 497, 504, 511, 516, 523, - 528, 535, 540, 547, 552, 559, 564, 571, 578, 585, 590, 597, - 455, 460, 467, 472, 479, 484, 491, 496, 505, 510, 517, 522, - 529, 534, 541, 546, 553, 558, 565, 570, 579, 584, 591, 596, - 456, 463, 468, 475, 480, 487, 492, 499, 506, 513, 518, 525, - 530, 537, 542, 549, 554, 561, 566, 573, 580, 587, 592, 599, - 457, 462, 469, 474, 481, 486, 493, 498, 507, 512, 519, 524, - 531, 536, 543, 548, 555, 560, 567, 572, 581, 586, 593, 598 }, - - { 640, 649, 654, 661, 666, 673, 678, 685, 690, 697, 702, 709, - 714, 723, 728, 735, 740, 747, 752, 759, 764, 771, 776, 783, - 641, 648, 655, 660, 667, 672, 679, 684, 691, 696, 703, 708, - 715, 722, 729, 734, 741, 746, 753, 758, 765, 770, 777, 782, - 642, 651, 656, 663, 668, 675, 680, 687, 692, 699, 704, 711, - 716, 725, 730, 737, 742, 749, 754, 761, 766, 773, 778, 785, - 643, 650, 657, 662, 669, 674, 681, 686, 693, 698, 705, 710, - 717, 724, 731, 736, 743, 748, 755, 760, 767, 772, 779, 784, - 644, 653, 658, 665, 670, 677, 682, 689, 694, 701, 706, 713, - 720, 727, 732, 739, 744, 751, 756, 763, 768, 775, 780, 787, - 645, 652, 659, 664, 671, 676, 683, 688, 695, 700, 707, 712, - 721, 726, 733, 738, 745, 750, 757, 762, 769, 774, 781, 786 }, - - { 830, 837, 842, 849, 854, 861, 868, 875, 880, 887, 892, 899, - 904, 911, 916, 923, 928, 937, 942, 949, 954, 961, 966, 973, - 831, 836, 843, 848, 855, 860, 869, 874, 881, 886, 893, 898, - 905, 910, 917, 922, 929, 936, 943, 948, 955, 960, 967, 972, - 832, 839, 844, 851, 856, 865, 870, 877, 882, 889, 894, 901, - 906, 913, 918, 925, 930, 939, 944, 951, 956, 963, 968, 975, - 833, 838, 845, 850, 857, 864, 871, 876, 883, 888, 895, 900, - 907, 912, 919, 924, 931, 938, 945, 950, 957, 962, 969, 974, - 834, 841, 846, 853, 858, 867, 872, 879, 884, 891, 896, 903, - 908, 915, 920, 927, 932, 941, 946, 953, 958, 965, 970, 977, - 835, 840, 847, 852, 859, 866, 873, 878, 885, 890, 897, 902, - 909, 914, 921, 926, 933, 940, 947, 952, 959, 964, 971, 976 }, - - { 1020, 1027, 1032, 1039, 1044, 1051, 1056, 1063, 1068, 1075, 1082, 1089, - 1094, 1101, 1106, 1113, 1118, 1125, 1130, 1137, 1142, 1149, 1156, 1163, - 1021, 1026, 1033, 1038, 1045, 1050, 1057, 1062, 1069, 1074, 1083, 1088, - 1095, 1100, 1107, 1112, 1119, 1124, 1131, 1136, 1143, 1148, 1157, 1162, - 1022, 1029, 1034, 1041, 1046, 1053, 1058, 1065, 1070, 1077, 1084, 1091, - 1096, 1103, 1108, 1115, 1120, 1127, 1132, 1139, 1144, 1153, 1158, 1165, - 1023, 1028, 1035, 1040, 1047, 1052, 1059, 1064, 1071, 1076, 1085, 1090, - 1097, 1102, 1109, 1114, 1121, 1126, 1133, 1138, 1145, 1152, 1159, 1164, - 1024, 1031, 1036, 1043, 1048, 1055, 1060, 1067, 1072, 1081, 1086, 1093, - 1098, 1105, 1110, 1117, 1122, 1129, 1134, 1141, 1146, 1155, 1160, 1167, - 1025, 1030, 1037, 1042, 1049, 1054, 1061, 1066, 1073, 1080, 1087, 1092, - 1099, 1104, 1111, 1116, 1123, 1128, 1135, 1140, 1147, 1154, 1161, 1166 }, - - { 1208, 1215, 1220, 1229, 1234, 1241, 1246, 1253, 1258, 1265, 1270, 1277, - 1282, 1289, 1296, 1303, 1308, 1315, 1320, 1327, 1332, 1339, 1344, 1351, - 1209, 1214, 1221, 1228, 1235, 1240, 1247, 1252, 1259, 1264, 1271, 1276, - 1283, 1288, 1297, 1302, 1309, 1314, 1321, 1326, 1333, 1338, 1345, 1350, - 1210, 1217, 1224, 1231, 1236, 1243, 1248, 1255, 1260, 1267, 1272, 1279, - 1284, 1291, 1298, 1305, 1310, 1317, 1322, 1329, 1334, 1341, 1346, 1353, - 1211, 1216, 1225, 1230, 1237, 1242, 1249, 1254, 1261, 1266, 1273, 1278, - 1285, 1290, 1299, 1304, 1311, 1316, 1323, 1328, 1335, 1340, 1347, 1352, - 1212, 1219, 1226, 1233, 1238, 1245, 1250, 1257, 1262, 1269, 1274, 1281, - 1286, 1293, 1300, 1307, 1312, 1319, 1324, 1331, 1336, 1343, 1348, 1355, - 1213, 1218, 1227, 1232, 1239, 1244, 1251, 1256, 1263, 1268, 1275, 1280, - 1287, 1292, 1301, 1306, 1313, 1318, 1325, 1330, 1337, 1342, 1349, 1354 }, - - { 1398, 1405, 1410, 1417, 1422, 1429, 1434, 1443, 1448, 1455, 1460, 1467, - 1472, 1479, 1484, 1491, 1496, 1503, 1508, 1517, 1522, 1529, 1534, 1541, - 1399, 1404, 1411, 1416, 1423, 1428, 1435, 1442, 1449, 1454, 1461, 1466, - 1473, 1478, 1485, 1490, 1497, 1502, 1509, 1516, 1523, 1528, 1535, 1540, - 1400, 1407, 1412, 1419, 1424, 1431, 1436, 1445, 1450, 1457, 1462, 1469, - 1474, 1481, 1486, 1493, 1498, 1505, 1512, 1519, 1524, 1531, 1536, 1543, - 1401, 1406, 1413, 1418, 1425, 1430, 1437, 1444, 1451, 1456, 1463, 1468, - 1475, 1480, 1487, 1492, 1499, 1504, 1513, 1518, 1525, 1530, 1537, 1542, - 1402, 1409, 1414, 1421, 1426, 1433, 1440, 1447, 1452, 1459, 1464, 1471, - 1476, 1483, 1488, 1495, 1500, 1507, 1514, 1521, 1526, 1533, 1538, 1545, - 1403, 1408, 1415, 1420, 1427, 1432, 1441, 1446, 1453, 1458, 1465, 1470, - 1477, 1482, 1489, 1494, 1501, 1506, 1515, 1520, 1527, 1532, 1539, 1544 }, - - { 1578, 1587, 1592, 1599, 1604, 1611, 1616, 1623, 1628, 1635, 1640, 1647, - 1652, 1661, 1666, 1673, 1678, 1685, 1690, 1697, 1702, 1709, 1714, 1721, - 1579, 1586, 1593, 1598, 1605, 1610, 1617, 1622, 1629, 1634, 1641, 1646, - 1653, 1660, 1667, 1672, 1679, 1684, 1691, 1696, 1703, 1708, 1715, 1720, - 1580, 1589, 1594, 1601, 1606, 1613, 1618, 1625, 1630, 1637, 1642, 1649, - 1656, 1663, 1668, 1675, 1680, 1687, 1692, 1699, 1704, 1711, 1716, 1723, - 1581, 1588, 1595, 1600, 1607, 1612, 1619, 1624, 1631, 1636, 1643, 1648, - 1657, 1662, 1669, 1674, 1681, 1686, 1693, 1698, 1705, 1710, 1717, 1722, - 1584, 1591, 1596, 1603, 1608, 1615, 1620, 1627, 1632, 1639, 1644, 1651, - 1658, 1665, 1670, 1677, 1682, 1689, 1694, 1701, 1706, 1713, 1718, 1725, - 1585, 1590, 1597, 1602, 1609, 1614, 1621, 1626, 1633, 1638, 1645, 1650, - 1659, 1664, 1671, 1676, 1683, 1688, 1695, 1700, 1707, 1712, 1719, 1724 }, - - }; - - size_t nof_samples = 0; - for(size_t i = 0; i < nof_voice_codewords; ++i) { - voice_codeword cw; - for(size_t j = 0; j < voice_codeword_sz; ++j) { - cw[j] = frame_body[voice_codeword_bits[i][j]]; - } - nof_samples += imbe.decode(cw, audio); - } - return nof_samples; -} - -uint16_t -ldu2::frame_size_max() const -{ - return 1728; + return string("LDU2"); } diff --git a/decoder/src/lib/ldu2.h b/decoder/src/lib/ldu2.h index de6cdbf..508482d 100644 --- a/decoder/src/lib/ldu2.h +++ b/decoder/src/lib/ldu2.h @@ -24,55 +24,31 @@ #ifndef INCLUDED_LDU2_H #define INCLUDED_LDU2_H -#include +#include /** - * P25 Logical Data Unit 2 (compressed IBME voice). + * P25 Logical Data Unit 2. */ -class ldu2 : public abstract_data_unit +class ldu2 : public voice_data_unit { public: /** * ldu2 constructor. * - * \param frame_body A bit_vector representing the frame body. + * \param frame_body A const_bit_queue representing the frame body. */ - ldu2(const_bit_vector& frame_body); + ldu2(const_bit_queue& frame_body); /** * ldu2 (virtual) destructor. */ virtual ~ldu2(); -protected: - /** - * Applies error correction code to the specified bit_vector. - * - * \param frame_body The bit vector to decode. + * Returns a string describing the Data Unit ID (DUID). */ - virtual void correct_errors(bit_vector& frame_body); - - /** - * Decode compressed audio using the supplied imbe_decoder and - * writes output to audio. - * - * \param frame_body The const_bit_vector to decode. - * \param imbe The imbe_decoder to use to generate the audio. - * \param audio A deque to which the audio (if any) is appended. - * \return The number of samples written to audio. - */ - virtual size_t decode_audio(const_bit_vector& frame_body, imbe_decoder& imbe, float_queue& audio); - - /** - * Returns the expected size (in bits) of this data_unit. For - * variable-length data this should return UINT16_MAX until the - * actual length of this frame is known. - * - * \return The expected size (in bits) of this data_unit when encoded. - */ - virtual uint16_t frame_size_max() const; + std::string duid_str() const; }; #endif /* INCLUDED_LDU2_H */ diff --git a/decoder/src/lib/op25.i b/decoder/src/lib/op25.i index b92af94..e5ef824 100644 --- a/decoder/src/lib/op25.i +++ b/decoder/src/lib/op25.i @@ -23,7 +23,7 @@ GR_SWIG_BLOCK_MAGIC(op25, decoder_ff); /* * Publicly-accesible constuctor function for op25_decoder_ff. */ -op25_decoder_ff_sptr op25_make_decoder_ff(); +op25_decoder_ff_sptr op25_make_decoder_ff(gr_msg_queue_sptr msgq); /* * The actual op25_decoder block. @@ -31,7 +31,7 @@ op25_decoder_ff_sptr op25_make_decoder_ff(); class op25_decoder_ff : public gr_block { private: - op25_decoder_ff(); + op25_decoder_ff(gr_msg_queue_sptr msgq); public: const char *device_name() const; }; diff --git a/decoder/src/lib/op25_decoder_ff.cc b/decoder/src/lib/op25_decoder_ff.cc index 0eeb39b..0b0d193 100644 --- a/decoder/src/lib/op25_decoder_ff.cc +++ b/decoder/src/lib/op25_decoder_ff.cc @@ -26,7 +26,6 @@ #endif #include -#include #include #include #include @@ -40,9 +39,9 @@ using namespace std; op25_decoder_ff_sptr -op25_make_decoder_ff() +op25_make_decoder_ff(gr_msg_queue_sptr msgq) { - return op25_decoder_ff_sptr(new op25_decoder_ff); + return op25_decoder_ff_sptr(new op25_decoder_ff(msgq)); } op25_decoder_ff::~op25_decoder_ff() @@ -56,7 +55,7 @@ void op25_decoder_ff::forecast(int nof_output_items, gr_vector_int &nof_input_items_reqd) { const size_t nof_inputs = nof_input_items_reqd.size(); - std::fill(&nof_input_items_reqd[0], &nof_input_items_reqd[nof_inputs], nof_output_items); + fill(&nof_input_items_reqd[0], &nof_input_items_reqd[nof_inputs], nof_output_items); } int @@ -82,7 +81,7 @@ op25_decoder_ff::general_work(int nof_output_items, gr_vector_int& nof_input_ite for(int i = 0; i < nof_output_items; ++i) { float *out = reinterpret_cast(&output_items[i]); - std::fill(&out[0], &out[nof_output_items], 0.0); // audio silence - for now + fill(&out[0], &out[nof_output_items], 0.0); // audio silence - for now } return nof_output_items; @@ -91,8 +90,7 @@ op25_decoder_ff::general_work(int nof_output_items, gr_vector_int& nof_input_ite exit(1); } catch(...) { cerr << "unhandled exception" << endl; - exit(2); - } + exit(2); } } const char* @@ -101,16 +99,16 @@ op25_decoder_ff::device_name() const return d_tap_device.c_str(); } -op25_decoder_ff::op25_decoder_ff() : +op25_decoder_ff::op25_decoder_ff(gr_msg_queue_sptr msgq) : gr_block("decoder_ff", gr_make_io_signature(1, 1, sizeof(float)), gr_make_io_signature(0, 1, sizeof(float))), + d_msgq(msgq), d_state(SYNCHRONIZING), + d_bad_NIDs(0), d_bch(63, 16, 11,"6 3 3 1 1 4 1 3 6 7 2 3 5 4 5 3", true), d_data_unit(), d_data_units(0), - d_frame_hdr(114), - d_fs(0), + d_frame_hdr(), d_imbe(imbe_decoder::make_imbe_decoder()), - d_symbol(0), d_tap(-1), d_tap_device("not available"), d_unrecognized(0) @@ -153,53 +151,112 @@ op25_decoder_ff::op25_decoder_ff() : } bool -op25_decoder_ff::correlates(dibit d) +op25_decoder_ff::correlated() { - size_t errs = 0; - const size_t ERR_THRESHOLD = 4; - const size_t NOF_FS_BITS = 48; - const frame_sync FS = 0x5575f5ff77ffLL; - const frame_sync FS_MASK = 0xffffffffffffLL; - d_fs = (d_fs << 2) | d; - d_fs &= FS_MASK; - size_t diff = FS ^ d_fs; - for(size_t i = 0; i < NOF_FS_BITS; ++i) { - if(diff & 0x1) { + static const bool FS[] = { + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 + }; + static const size_t FS_SZ = sizeof(FS)/sizeof(FS[0]); + + uint8_t errs = 0; + for(size_t i = 0; i < FS_SZ; ++i) { + if(d_frame_hdr[i] ^ FS[i]) { ++errs; } - diff >>= 1; } - return errs < ERR_THRESHOLD; + return (errs <= 6); +} + +bool +op25_decoder_ff::identified() +{ + static const size_t NID[] = { + 63, 62, 61, 60, 59, 58, 57, 56, + 55, 54, 53, 52, 51, 50, 49, 48, + 112, 111, 110, 109, 108, 107, 106, 105, + 104, 103, 102, 101, 100, 99, 98, 97, + 96, 95, 94, 93, 92, 91, 90, 89, + 88, 87, 86, 85, 84, 83, 82, 81, + 80, 79, 78, 77, 76, 75, 74, 73, + 72, 69, 68, 67, 66, 65, 64, + }; + size_t NID_SZ = sizeof(NID) / sizeof(NID[0]); + + itpp::bvec b(63), zeroes(16); + swab(d_frame_hdr, NID, NID_SZ, b, 0); + b = d_bch.decode(b); + if(b != zeroes) { + b = d_bch.encode(b); + unswab(b, 0, d_frame_hdr, NID, NID_SZ); + d_data_unit = data_unit::make_data_unit(d_frame_hdr); + } else { + + cout << __PRETTY_FUNCTION__ << ":" << __LINE__ << "NID decode error" << endl; + cout << "\tNID="; + for(int i = 0; i < b.size(); ++i) { + cout << b[i] << ","; + } + cout << endl; + + ++d_bad_NIDs; + data_unit_sptr null; + d_data_unit = null; + } + return d_data_unit; +} + + +void +op25_decoder_ff::process_data_unit() +{ + const size_t msg_hdr_sz = 14; + const size_t msg_sz = d_data_unit->data_size(); + const size_t total_msg_sz = msg_hdr_sz + msg_sz; + uint8_t msg_data[total_msg_sz]; + if(d_data_unit->decode(msg_sz, msg_data + msg_hdr_sz, *d_imbe, d_audio)) { + if(-1 != d_tap) { + memset(&msg_data[0], 0xff, 6); + memset(&msg_data[6], 0x00, 6); + memset(&msg_data[12], 0xff, 2); + write(d_tap, msg_data, total_msg_sz); + } + if(d_msgq) { + string snapshot(d_data_unit->snapshot()); + if(snapshot.size() > 0) { + const size_t snapshot_sz = snapshot.size() + 1; + gr_message_sptr msg = gr_make_message(/*type*/0, /*arg1*/++d_data_units, /*arg2*/0, snapshot_sz); + char *snapshot_data = reinterpret_cast(msg->msg()); + memcpy(snapshot_data, snapshot.c_str(), snapshot_sz); + d_msgq->handle(msg); + } + } + } } void op25_decoder_ff::receive_symbol(dibit d) { + d_frame_hdr.push_back(d & 0x2); + d_frame_hdr.push_back(d & 0x1); + const size_t frame_hdr_sz = d_frame_hdr.size(); + switch(d_state) { case SYNCHRONIZING: - if(correlates(d)) { - d_symbol = 23; - d_state = IDENTIFYING; - swab(d_fs, 47, -1, d_frame_hdr, 0); + if(48 <= frame_hdr_sz) { + d_frame_hdr.erase(d_frame_hdr.begin(), d_frame_hdr.begin() + (frame_hdr_sz - 48)); + if(correlated()) { + d_state = IDENTIFYING; + } } break; case IDENTIFYING: - ++d_symbol; - d_frame_hdr[2 * d_symbol] = d & 2; - d_frame_hdr[(2 * d_symbol) + 1] = d & 1; - if(56 == d_symbol) { - itpp::bvec b(63); - swab(d_frame_hdr, 63, 47, b, 0); - swab(d_frame_hdr, 112, 71, b, 16); - swab(d_frame_hdr, 69, 63, b, 57); - b = d_bch.decode(b); -#if __x86_64 - unswab(b, 57, d_frame_hdr, 69, 63); - unswab(b, 16, d_frame_hdr, 112, 71); - unswab(b, 0, d_frame_hdr, 63, 47); -#endif - d_data_unit = data_unit::make_data_unit(d_frame_hdr); - if(d_data_unit) { + if(114 <= frame_hdr_sz) { + if(identified()) { d_state = READING; } else { ++d_unrecognized; @@ -210,16 +267,7 @@ op25_decoder_ff::receive_symbol(dibit d) case READING: d_data_unit->extend(d); if(d_data_unit->is_complete()) { - const size_t msg_hdr_sz = 14; - const size_t msg_sz = d_data_unit->data_size(); - const size_t total_msg_sz = msg_hdr_sz + msg_sz; - uint8_t msg_data[total_msg_sz]; - if(d_data_unit->decode(msg_sz, msg_data + msg_hdr_sz, *d_imbe, d_audio) && (-1 != d_tap)) { - memset(&msg_data[0], 0xff, 6); - memset(&msg_data[6], 0x00, 6); - memset(&msg_data[12], 0xff, 2); - write(d_tap, msg_data, total_msg_sz); - } + process_data_unit(); data_unit_sptr null; d_data_unit = null; d_state = SYNCHRONIZING; diff --git a/decoder/src/lib/op25_decoder_ff.h b/decoder/src/lib/op25_decoder_ff.h index a77263f..b680acc 100644 --- a/decoder/src/lib/op25_decoder_ff.h +++ b/decoder/src/lib/op25_decoder_ff.h @@ -24,18 +24,16 @@ #ifndef INCLUDED_OP25_DECODER_FF_H #define INCLUDED_OP25_DECODER_FF_H -#include #include #include +#include #include #include #include typedef boost::shared_ptr op25_decoder_ff_sptr; -op25_decoder_ff_sptr op25_make_decoder_ff(); - -typedef uint64_t frame_sync; +op25_decoder_ff_sptr op25_make_decoder_ff(gr_msg_queue_sptr msgq); /** * op25_decoder_ff is a GNU Radio block for decoding APCO P25 @@ -77,41 +75,60 @@ private: * op25_decoder_ff and wrap it in a shared_ptr. This is effectively * the public constructor. */ - friend op25_decoder_ff_sptr op25_make_decoder_ff(); + friend op25_decoder_ff_sptr op25_make_decoder_ff(gr_msg_queue_sptr msgq); /** * op25_decoder_ff protected constructor. */ - op25_decoder_ff(); + op25_decoder_ff(gr_msg_queue_sptr msgq); /** - * Tests whether the received dibit symbol completes a frame sync - * sequence. Returns true when d completes a frame sync bit string - * otherwise returns false. When found d_fs contains the frame sync - * value. + * Tests whether d_frame_header correlates with the APCO P25 frame + * sync sequence. This method must only be called when the frame + * header is larger than 48 bits in length (the minimum size for + * the FS). * - * \param d The symbol to process. + * \return true if the frame header correlates; otherwise false. */ - bool correlates(dibit d); + bool correlated(); /** - * Process a received symbol. + * Tests whether d_frame_header identifies a known data unit and if + * so sets d_data_unit to point to an appropriate instance. This + * method must only be called when the frame header is larger than + * 114 bits in length (the minimum size for a frame containing a + * NID). + * + * \return true if the frame header identifies a known data unit; + * otherwise false. + */ + bool identified(); + + /** + * Process the completed data_unit (pointed at by + * d_data_unit). This decodes the data_unit and then sends the + * result to wireshark. Attempts to snapshot the data_unit and, if + * successfull, it passes the result to the user interface. + */ + void process_data_unit(); + + /** + * Handle a received symbol. * * \param d The symbol to process. */ void receive_symbol(dibit d); private: - + gr_msg_queue_sptr d_msgq; enum { SYNCHRONIZING, IDENTIFYING, READING } d_state; float_queue d_audio; + uint32_t d_bad_NIDs; itpp::BCH d_bch; data_unit_sptr d_data_unit; uint32_t d_data_units; - bit_vector d_frame_hdr; - frame_sync d_fs; + bit_queue d_frame_hdr; imbe_decoder_sptr d_imbe; - uint32_t d_symbol; int32_t d_tap; std::string d_tap_device; uint32_t d_unrecognized; diff --git a/decoder/src/lib/pdu.cc b/decoder/src/lib/pdu.cc index 9e39d56..b6bf29c 100644 --- a/decoder/src/lib/pdu.cc +++ b/decoder/src/lib/pdu.cc @@ -23,7 +23,9 @@ #include -pdu::pdu(const_bit_vector& frame_body) : +using std::string; + +pdu::pdu(const_bit_queue& frame_body) : abstract_data_unit(frame_body) { } @@ -31,6 +33,12 @@ pdu::~pdu() { } +string +pdu::duid_str() const +{ + return string("PDU"); +} + void pdu::correct_errors(bit_vector& frame_body) { diff --git a/decoder/src/lib/pdu.h b/decoder/src/lib/pdu.h index 663cd1d..373a88b 100644 --- a/decoder/src/lib/pdu.h +++ b/decoder/src/lib/pdu.h @@ -36,15 +36,20 @@ public: /** * P25 packet data unit (PDU) constructor. * - * \param frame_body A const_bit_vector representing the frame body. + * \param frame_body A const_bit_queue representing the frame body. */ - pdu(const_bit_vector& frame_body); + pdu(const_bit_queue& frame_body); /** * pdu (virtual) destructor. */ virtual ~pdu(); + /** + * Returns a string describing the Data Unit ID (DUID). + */ + std::string duid_str() const; + protected: /** diff --git a/decoder/src/lib/swab.h b/decoder/src/lib/swab.h index 3d7acc4..3b1ee7c 100644 --- a/decoder/src/lib/swab.h +++ b/decoder/src/lib/swab.h @@ -3,48 +3,47 @@ #include #include -#include #include typedef std::vector bit_vector; typedef const std::vector const_bit_vector; /** - * Swab bits from in[begin, end) to out[where,...). + * Swab in[bits[0..nof_bits)) to out[where..where+nof_bits). * - * \param in A uint64_t representing a set of bits. - * \param begin The offset of the first bit to copy. - * \param end The offset of the end bit (this bit is not copied). - * \param out The bit_vector into which bits are copied. - * \param where The starting point for writing bits. + * \param in A const reference to the source. + * \param bits An array specifying the ordinals of the bits to copy. + * \param bits_sz The size of the bits array. + * \param out A reference to the destination. + * \param where The offset of the first bit to write. */ -inline void -swab(uint64_t in, int begin, int end, bit_vector& out, int where) +template +void swab(const X& in, const size_t bits[], size_t bits_sz, Y& out, size_t where) { - for(int i = begin; i != end; (begin < end ? ++i : --i)) { - out[where++] = (in & (1 << i) ? 1 : 0); + for(size_t i = 0; i < bits_sz; ++i) { + out[where+i] = in[bits[i]]; } } /** - * Swab bits from in[begin, end) to out[where,...). + * Swab from in[0..nof_bits) to out[bits[0..nof_bits)). * - * \param in A const_bit_vector reference to the source. - * \param begin The offset of the first bit to copy. - * \param end The offset of the end bit (this bit is not copied). - * \param out A bvec into which bits are copied. - * \param where The starting point for writing bits. + * \param in A const bvec reference to the source. + * \param where The offset of the first bit to read. + * \param out A bit_vector reference to the destination. + * \param bits An array specifying the ordinals of the bits to copy. + * \param bits_sz The size of the bits array. */ -inline void -swab(const_bit_vector& in, int begin, int end, itpp::bvec& out, int where) +template +void unswab(const X& in, size_t where, Y& out, const size_t bits[], size_t bits_sz) { - for(int i = begin; i != end; (begin < end ? ++i : --i)) { - out[where++] = in[i]; + for(size_t i = 0; i < bits_sz; ++i) { + out[bits[i]] = in[where+i]; } } /** - * Swabs a bit_vector in[begin,end) to an octet buffer. + * Extract a bit_vector in[begin,end) to an octet buffer. * * \param in A const reference to the bit_vector. * \param begin The offset of the first bit to copy. @@ -52,52 +51,16 @@ swab(const_bit_vector& in, int begin, int end, itpp::bvec& out, int where) * \param out Address of the octet buffer to write into. * \return The number of octers written. */ -inline size_t -swab(const_bit_vector& in, int begin, int end, uint8_t *out) +template +size_t extract(const X& in, int begin, int end, uint8_t *out) { const size_t out_sz = (7 + abs(end - begin)) / 8; memset(out, 0, out_sz); - for(int i = begin, j = 0; i != end; (begin < end ? ++i : --i), ++j) { + for(int i = begin, j = 0; i < end; ++i, ++j) { out[j / 8] ^= in[i] << (7 - (j % 8)); } return out_sz; } -/** - * Swabs a bitset in[begin,end) to an octet buffer. - * - * \param in A const reference to the bitset. - * \param begin The offset of the first bit to copy. - * \param end The offset of the end bit (this bit is not copied). - * \param out Address of the octet buffer to write into. - * \return The number of octers written. - */ -template size_t -swab(const std::bitset& in, int begin, int end, uint8_t *out) -{ - const size_t out_sz = (7 + abs(end - begin)) / 8; - memset(out, 0, out_sz); - for(int i = begin, j = 0; i != end; (begin < end ? ++i : --i), ++j) { - out[j / 8] ^= in[i] << (7 - (j % 8)); - } - return out_sz; -} - -/** - * Swab bits from bvec in[where] in to out[begin,end). - * - * \param in A const reference to the bvec. - * \param begin The offset of the first bit to copy. - * \param end The offset of the end bit. - * \param out A bvec into which bits are written. - * \param where The starting point for writing bits. - */ -inline void -unswab(const itpp::bvec& in, int where, bit_vector& out, int begin, int end) -{ - for(int i = begin; i != end; (begin < end ? ++i : --i)) { - out[i] = in[where++]; - } -} /** * Extract value of bits from in[begin,end). @@ -107,11 +70,11 @@ unswab(const itpp::bvec& in, int where, bit_vector& out, int begin, int end) * \param end The offset of the end bit. * \return A uint64_t containing the value */ -inline uint64_t -extract(const_bit_vector& in, int begin, int end) +template +uint64_t extract(const X& in, int begin, int end) { uint64_t x = 0LL; - for(int i = begin; i != end; (begin < end ? ++i : --i)) { + for(int i = begin; i < end; ++i) { x = (x << 1) | (in[i] ? 1 : 0); } return x; diff --git a/decoder/src/lib/tdu.cc b/decoder/src/lib/tdu.cc index b37a078..733d1f6 100644 --- a/decoder/src/lib/tdu.cc +++ b/decoder/src/lib/tdu.cc @@ -27,7 +27,9 @@ #include #include -tdu::tdu(const_bit_vector& frame_body, bool has_link_control) : +using std::string; + +tdu::tdu(const_bit_queue& frame_body, bool has_link_control) : abstract_data_unit(frame_body), d_has_link_control(has_link_control) { @@ -37,6 +39,12 @@ tdu::~tdu() { } +string +tdu::duid_str() const +{ + return string("TDU"); +} + void tdu::correct_errors(bit_vector& frame) { diff --git a/decoder/src/lib/tdu.h b/decoder/src/lib/tdu.h index f396e16..85380ff 100644 --- a/decoder/src/lib/tdu.h +++ b/decoder/src/lib/tdu.h @@ -36,16 +36,21 @@ public: /** * tdu constructor. * - * \param frame_body A const_bit_vector representing the frame body. + * \param frame_body A const_bit_queue representing the frame body. * \param has_link_control true if frame has link control data, otherwise false. */ - tdu(const_bit_vector& frame_body, bool has_link_control); + tdu(const_bit_queue& frame_body, bool has_link_control); /** * tdu constructor. */ virtual ~tdu(); + /** + * Returns a string describing the Data Unit ID (DUID). + */ + std::string duid_str() const; + protected: /** diff --git a/decoder/src/lib/vc55_imbe_decoder.cc b/decoder/src/lib/vc55_imbe_decoder.cc index 5ed1f77..07c155c 100644 --- a/decoder/src/lib/vc55_imbe_decoder.cc +++ b/decoder/src/lib/vc55_imbe_decoder.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -74,8 +75,7 @@ vc55_imbe_decoder::decode(voice_codeword& in_out, audio_output& out) uint8_t packet[20]; packet[0] = 0x56; packet[1] = 0xf0; - - swab(in_out, 0, 144, &packet[2]); + /* ToDo: extract(in_out, 0, 144, &packet[2]); */ if(-1 == write(d_fd, packet, sizeof(packet))) { perror("write(d_fd, packet, sizeof(packet))"); close(d_fd); diff --git a/decoder/src/python/qa_op25.py b/decoder/src/python/qa_op25.py index 030cd17..399ab31 100755 --- a/decoder/src/python/qa_op25.py +++ b/decoder/src/python/qa_op25.py @@ -39,7 +39,8 @@ class qa_op25(gr_unittest.TestCase): def test_constructor(self): framing_sequence = (3, 3, 3, 3, 3, -3, 3, 3, -3, -3, 3, 3, -3, -3, -3, -3, 3, -3, 3, -3, -3, -3, -3, -3) src = gr.vector_source_f(framing_sequence, False) - p25 = op25.decoder_ff() + msgq = gr.msg_queue() + p25 = op25.decoder_ff(msgq) self.fg.connect(src, p25) # ToDo: add test cases! diff --git a/python/usrp_p25_rx.py b/python/usrp_p25_rx.py index 53d921c..5bae805 100755 --- a/python/usrp_p25_rx.py +++ b/python/usrp_p25_rx.py @@ -186,6 +186,12 @@ class p25_rx_block (stdgui2.std_top_block): toolbar_new = self.toolbar.AddSimpleTool(wx.ID_NEW, new_icon, u"New Capture") open_icon = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, icon_size) toolbar_open = self.toolbar.AddSimpleTool(wx.ID_OPEN, open_icon, u"Open") + # + # self.toolbar.AddSeparator() + # self.gain_control = wx.Slider(self.toolbar, 100, 50, 1, 100, style=wx.SL_HORIZONTAL) + # slider.SetTickFreq(5, 1) + # self.toolbar.AddControl(self.gain_control) + # self.toolbar.Realize() else: self.toolbar = None @@ -210,8 +216,10 @@ class p25_rx_block (stdgui2.std_top_block): # Traffic snapshot self.traffic = TrafficPane(self.notebook) self.notebook.AddPage(self.traffic, "Traffic") - # The P25 decoder - self.p25_decoder = op25.decoder_ff() + # Setup the decoder and report the TUN/TAP device name + msgq = gr.msg_queue(2) + self.decode_watcher = decode_watcher(msgq, self.traffic) + self.p25_decoder = op25.decoder_ff(msgq) self.frame.SetStatusText("TUN/TAP: " + self.p25_decoder.device_name()) # read capture file properties (decimation etc.) @@ -283,6 +291,7 @@ class p25_rx_block (stdgui2.std_top_block): self.spectrum_plotter.Clear() self.signal_plotter.Clear() self.symbol_plotter.Clear() + self.traffic.clear() elif "RUNNING" == self.state: # menu items self.file_new.Enable(False) @@ -362,7 +371,7 @@ class p25_rx_block (stdgui2.std_top_block): self.stop() self.wait() # ToDo: get open_usrp() arguments from wizard - self.open_usrp((1,0), 128, None, 468.0e06, True) + self.open_usrp((0,0), 256, None, 434.08e06, True) self.start() # Open an existing capture @@ -460,33 +469,33 @@ class TrafficPane(wx.Panel): label = wx.StaticText(self, -1, "DUID:") sizer.Add(label, pos=(1,1)) - field = wx.TextCtrl(self, -1, "", size=(175, -1), style=wx.TE_READONLY) + field = wx.TextCtrl(self, -1, "", size=(72, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(1,2)) self.fields["duid"] = field; - label = wx.StaticText(self, -1, "Source:") + label = wx.StaticText(self, -1, "NAC:") sizer.Add(label, pos=(2,1)) field = wx.TextCtrl(self, -1, "", size=(175, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(2,2)) - self.fields["source"] = field; + self.fields["nac"] = field; - label = wx.StaticText(self, -1, "Destination:") + label = wx.StaticText(self, -1, "Source:") sizer.Add(label, pos=(3,1)) field = wx.TextCtrl(self, -1, "", size=(175, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(3,2)) - self.fields["dest"] = field; + self.fields["source"] = field; - label = wx.StaticText(self, -1, "NID:") + label = wx.StaticText(self, -1, "Destination:") sizer.Add(label, pos=(4,1)) field = wx.TextCtrl(self, -1, "", size=(175, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(4,2)) - self.fields["nid"] = field; + self.fields["dest"] = field; - label = wx.StaticText(self, -1, "NAC:") + label = wx.StaticText(self, -1, "NID:") sizer.Add(label, pos=(5,1)) field = wx.TextCtrl(self, -1, "", size=(175, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(5,2)) - self.fields["nac"] = field; + self.fields["nid"] = field; label = wx.StaticText(self, -1, "MFID:") sizer.Add(label, pos=(1,4)) @@ -502,19 +511,19 @@ class TrafficPane(wx.Panel): label = wx.StaticText(self, -1, "KID:") sizer.Add(label, pos=(3,4)) - field = wx.TextCtrl(self, -1, "", size=(175, -1), style=wx.TE_READONLY) + field = wx.TextCtrl(self, -1, "", size=(72, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(3,5)) self.fields["kid"] = field; label = wx.StaticText(self, -1, "MI:") sizer.Add(label, pos=(4,4)) - field = wx.TextCtrl(self, -1, "", size=(175, -1), style=wx.TE_READONLY) + field = wx.TextCtrl(self, -1, "", size=(216, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(4,5)) self.fields["mi"] = field; label = wx.StaticText(self, -1, "TGID:") sizer.Add(label, pos=(5,4)) - field = wx.TextCtrl(self, -1, "", size=(175, -1), style=wx.TE_READONLY) + field = wx.TextCtrl(self, -1, "", size=(72, -1), style=wx.TE_READONLY) sizer.Add(field, pos=(5,5)) self.fields["tgid"] = field; @@ -603,7 +612,7 @@ class demod_watcher(threading.Thread): # class decode_watcher(threading.Thread): - def __init__(self, msgq, traffic_pane, **kwds): + def __init__(self, msgq, traffic_pane, **kwds): threading.Thread.__init__ (self, **kwds) self.setDaemon(1) self.msgq = msgq @@ -614,8 +623,9 @@ class decode_watcher(threading.Thread): def run(self): while(self.keep_running): msg = self.msgq.delete_head() - # pickle_dict = msg.arg1() - self.callback(frequency_correction) + pickled_dict = msg.to_string() + attrs = pickle.loads(pickled_dict) + self.traffic_pane.update(attrs) # Start the receiver diff --git a/samples/p25-plain-silence.dat.info b/samples/p25-plain-silence.dat.info index c7f94a0..dc2a0b6 100644 --- a/samples/p25-plain-silence.dat.info +++ b/samples/p25-plain-silence.dat.info @@ -2,8 +2,14 @@ S'capture-rate' p1 I250000 -sS'capture-dev' +sS'source-decim' p2 -S'USRP1' +I256 +sS'source-dev' p3 +S'USRP' +p4 +sS'center-freq' +p5 +F434075000.0 s. \ No newline at end of file