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<bool>) 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
This commit is contained in:
parent
e54eca540b
commit
fa75c57851
|
@ -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
|
||||
|
|
|
@ -25,8 +25,10 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
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
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#define INCLUDED_ABSTRACT_DATA_UNIT_H
|
||||
|
||||
#include <data_unit.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
|
|
|
@ -26,12 +26,12 @@
|
|||
#include <ldu1.h>
|
||||
#include <ldu2.h>
|
||||
#include <pdu.h>
|
||||
#include <swab.h>
|
||||
#include <tdu.h>
|
||||
|
||||
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) {
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#include <stdint.h>
|
||||
#include <swab.h>
|
||||
|
||||
typedef std::deque<bool> bit_queue;
|
||||
typedef const std::deque<bool> const_bit_queue;
|
||||
|
||||
typedef uint8_t dibit;
|
||||
|
||||
typedef std::deque<float> 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:
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
#include <itpp/comm/egolay.h>
|
||||
#include <itpp/comm/reedsolomon.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -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:
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
#ifndef INCLUDED_IMBE_DECODER_H
|
||||
#define INCLUDED_IMBE_DECODER_H
|
||||
|
||||
#include <bitset>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
|
||||
typedef std::bitset<144> voice_codeword;
|
||||
typedef std::deque<float> audio_output;
|
||||
typedef std::vector<bool> voice_codeword;
|
||||
|
||||
typedef boost::shared_ptr<class imbe_decoder> imbe_decoder_sptr;
|
||||
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
|
||||
#include <ldu1.h>
|
||||
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -24,58 +24,31 @@
|
|||
#ifndef INCLUDED_LDU1_H
|
||||
#define INCLUDED_LDU1_H
|
||||
|
||||
#include <abstract_data_unit.h>
|
||||
#include <voice_data_unit.h>
|
||||
|
||||
/**
|
||||
* 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<float> 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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
|
||||
#include <ldu2.h>
|
||||
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -24,55 +24,31 @@
|
|||
#ifndef INCLUDED_LDU2_H
|
||||
#define INCLUDED_LDU2_H
|
||||
|
||||
#include <abstract_data_unit.h>
|
||||
#include <voice_data_unit.h>
|
||||
|
||||
/**
|
||||
* 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<float> 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 */
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <bitset>
|
||||
#include <gr_io_signature.h>
|
||||
#include <gr_message.h>
|
||||
#include <iostream>
|
||||
|
@ -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<float*>(&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<char*>(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;
|
||||
|
|
|
@ -24,18 +24,16 @@
|
|||
#ifndef INCLUDED_OP25_DECODER_FF_H
|
||||
#define INCLUDED_OP25_DECODER_FF_H
|
||||
|
||||
#include <bitset>
|
||||
#include <data_unit.h>
|
||||
#include <gr_block.h>
|
||||
#include <gr_msg_queue.h>
|
||||
#include <imbe_decoder.h>
|
||||
#include <itpp/comm/bch.h>
|
||||
#include <string>
|
||||
|
||||
typedef boost::shared_ptr<class op25_decoder_ff> 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;
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
|
||||
#include <pdu.h>
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,48 +3,47 @@
|
|||
|
||||
#include <bitset>
|
||||
#include <itpp/base/vec.h>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<bool> bit_vector;
|
||||
typedef const std::vector<bool> 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 <class X, class Y>
|
||||
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 <class X, class Y>
|
||||
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<class X>
|
||||
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<N> 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 N> size_t
|
||||
swab(const std::bitset<N>& 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<class X>
|
||||
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;
|
||||
|
|
|
@ -27,7 +27,9 @@
|
|||
#include <swab.h>
|
||||
#include <tdu.h>
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <cerrno>
|
||||
#include <sstream>
|
||||
#include <fcntl.h>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <swab.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -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);
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
Reference in New Issue