git-svn-id: http://op25.osmocom.org/svn/trunk@325 65a5c917-d112-43f1-993d-58c26a4786be
This commit is contained in:
max 2013-09-25 03:33:58 +00:00
parent 86373169c7
commit 6e6539571f
3 changed files with 179 additions and 3 deletions

View File

@ -39,7 +39,7 @@ public:
uint32_t nac; // extracted NAC
uint32_t duid; // extracted DUID
bit_vector frame_body; // all bits in frame
size_t frame_size; // number of bits in frame_body
uint32_t frame_size; // number of bits in frame_body
uint32_t bch_errors; // number of errors detected in bch
};

View File

@ -20,7 +20,7 @@
* Boston, MA 02111-1307, USA.
*/
/*
* Copyright 2010, KA1RBI
* Copyright 2010, 2011, 2012, 2013 KA1RBI
*/
/*
* config.h is generated by configure. It contains the results
@ -62,6 +62,133 @@ repeater_make_p25_frame_assembler (const char* udp_host, int port, int debug, bo
static const int MIN_IN = 1; // mininum number of input streams
static const int MAX_IN = 1; // maximum number of input streams
static uint16_t crc16(uint8_t buf[], int len) {
uint32_t poly = (1<<12) + (1<<5) + (1<<0);
uint32_t crc = 0;
for(int i=0; i<len; i++) {
uint8_t bits = buf[i];
for (int j=0; j<8; j++) {
uint8_t bit = (bits >> (7-j)) & 1;
crc = ((crc << 1) | bit) & 0x1ffff;
if (crc & 0x10000)
crc = (crc & 0xffff) ^ poly;
}
}
crc = crc ^ 0xffff;
return crc & 0xffff;
}
/* find_min is from wireshark/plugins/p25/packet-p25cai.c */
/* Copyright 2008, Michael Ossmann <mike@ossmann.com> */
/* return the index of the lowest value in a list */
static int
find_min(uint8_t list[], int len)
{
int min = list[0];
int index = 0;
int unique = 1;
int i;
for (i = 1; i < len; i++) {
if (list[i] < min) {
min = list[i];
index = i;
unique = 1;
} else if (list[i] == min) {
unique = 0;
}
}
/* return -1 if a minimum can't be found */
if (!unique)
return -1;
return index;
}
/* count_bits is from wireshark/plugins/p25/packet-p25cai.c */
/* Copyright 2008, Michael Ossmann <mike@ossmann.com> */
/* count the number of 1 bits in an int */
static int
count_bits(unsigned int n)
{
int i = 0;
for (i = 0; n != 0; i++)
n &= n - 1;
return i;
}
/* adapted from wireshark/plugins/p25/packet-p25cai.c */
/* Copyright 2008, Michael Ossmann <mike@ossmann.com> */
/* deinterleave and trellis1_2 decoding */
/* tsbk_buf is assumed to be a buffer of 12 bytes */
static int
tsbk_deinterleave(bit_vector& bv, unsigned int start, uint8_t* tsbk_buf)
{
static const uint16_t deinterleave_tb[] = {
0, 1, 2, 3, 52, 53, 54, 55, 100,101,102,103, 148,149,150,151,
4, 5, 6, 7, 56, 57, 58, 59, 104,105,106,107, 152,153,154,155,
8, 9, 10, 11, 60, 61, 62, 63, 108,109,110,111, 156,157,158,159,
12, 13, 14, 15, 64, 65, 66, 67, 112,113,114,115, 160,161,162,163,
16, 17, 18, 19, 68, 69, 70, 71, 116,117,118,119, 164,165,166,167,
20, 21, 22, 23, 72, 73, 74, 75, 120,121,122,123, 168,169,170,171,
24, 25, 26, 27, 76, 77, 78, 79, 124,125,126,127, 172,173,174,175,
28, 29, 30, 31, 80, 81, 82, 83, 128,129,130,131, 176,177,178,179,
32, 33, 34, 35, 84, 85, 86, 87, 132,133,134,135, 180,181,182,183,
36, 37, 38, 39, 88, 89, 90, 91, 136,137,138,139, 184,185,186,187,
40, 41, 42, 43, 92, 93, 94, 95, 140,141,142,143, 188,189,190,191,
44, 45, 46, 47, 96, 97, 98, 99, 144,145,146,147, 192,193,194,195,
48, 49, 50, 51 };
uint8_t hd[4];
int b, d, j;
int state = 0;
uint8_t codeword;
uint16_t crc;
static const uint8_t next_words[4][4] = {
{0x2, 0xC, 0x1, 0xF},
{0xE, 0x0, 0xD, 0x3},
{0x9, 0x7, 0xA, 0x4},
{0x5, 0xB, 0x6, 0x8}
};
memset(tsbk_buf, 0, 12);
for (b=0; b < 98*2; b += 4) {
codeword = (bv[start+deinterleave_tb[b+0]] << 3) +
(bv[start+deinterleave_tb[b+1]] << 2) +
(bv[start+deinterleave_tb[b+2]] << 1) +
bv[start+deinterleave_tb[b+3]] ;
/* try each codeword in a row of the state transition table */
for (j = 0; j < 4; j++) {
/* find Hamming distance for candidate */
hd[j] = count_bits(codeword ^ next_words[state][j]);
}
/* find the dibit that matches the most codeword bits (minimum Hamming distance) */
state = find_min(hd, 4);
/* error if minimum can't be found */
if(state == -1)
return -1; // decode error, return failure
/* It also might be nice to report a condition where the minimum is
* non-zero, i.e. an error has been corrected. It probably shouldn't
* be a permanent failure, though.
*
* DISSECTOR_ASSERT(hd[state] == 0);
*/
/* append dibit onto output buffer */
d = b >> 2; // dibit ctr
if (d < 48) {
tsbk_buf[d >> 2] |= state << (6 - ((d%4) * 2));
}
}
crc = crc16(tsbk_buf, 12);
if (crc != 0)
return -1; // trellis decode OK, but CRC error occurred
return 0; // return OK code
}
/*
* The private constructor
*/
@ -76,6 +203,7 @@ repeater_p25_frame_assembler::repeater_p25_frame_assembler (const char* udp_host
d_debug(debug),
d_do_imbe(do_imbe),
d_do_output(do_output),
d_do_msgq(do_msgq),
d_msg_queue(queue),
symbol_queue(),
framer(new p25_framer())
@ -102,6 +230,21 @@ repeater_p25_frame_assembler::forecast(int nof_output_items, gr_vector_int &nof_
nof_samples_reqd = 3.0 * nof_output_items;
std::fill(&nof_input_items_reqd[0], &nof_input_items_reqd[nof_inputs], nof_samples_reqd);
}
void
repeater_p25_frame_assembler::process_tsbk(uint32_t const nac, uint8_t const tsbk_buf[])
{
char wbuf[12];
if (!d_do_msgq)
return;
if (d_msg_queue->full_p())
return;
memcpy(wbuf, tsbk_buf, 10);
wbuf[10] = (nac >> 8) & 0xff;
wbuf[11] = nac & 0xff;
gr_message_sptr msg = gr_make_message_from_string(std::string(wbuf, 12), 0, 0, 0);
d_msg_queue->insert_tail(msg);
// msg.reset();
}
int
repeater_p25_frame_assembler::general_work (int noutput_items,
@ -115,7 +258,39 @@ repeater_p25_frame_assembler::general_work (int noutput_items,
for (int i = 0; i < noutput_items; i++){
if(framer->rx_sym(in[i])) { // complete frame was detected
if (d_debug >= 10) {
fprintf (stderr, "NAC 0x%X DUID 0x%X len %d errs %d ", framer->nac, framer->duid, framer->frame_size >> 1, framer->bch_errors);
fprintf (stderr, "NAC 0x%X DUID 0x%X len %u errs %u ", framer->nac, framer->duid, framer->frame_size >> 1, framer->bch_errors);
}
if (framer->duid == 0x07 && framer->bch_errors >= 0) {
unsigned int d, b;
int rc;
bit_vector bv1(720);
uint8_t tsbk_buf[12];
if (framer->frame_size > 720) {
fprintf(stderr, "warning trunk frame size %u exceeds maximum\n", framer->frame_size);
framer->frame_size = 720;
}
for (d=0, b=0; d < framer->frame_size >> 1; d++) {
if ((d+1) % 36 == 0)
continue; // skip SS
bv1[b++] = framer->frame_body[d*2];
bv1[b++] = framer->frame_body[d*2+1];
}
if (framer->frame_size >= 360) {
rc = tsbk_deinterleave(bv1,48+64 , tsbk_buf);
if (rc == 0)
process_tsbk(framer->nac, tsbk_buf);
}
if (framer->frame_size >= 576) {
rc = tsbk_deinterleave(bv1,48+64+196 , tsbk_buf);
if (rc == 0)
process_tsbk(framer->nac, tsbk_buf);
}
if (framer->frame_size >= 720) {
rc = tsbk_deinterleave(bv1,48+64+196+196, tsbk_buf);
if (rc == 0)
process_tsbk(framer->nac, tsbk_buf);
}
}
if (d_debug >= 10 && framer->duid == 0x00) {
ProcHDU(framer->frame_body);

View File

@ -77,6 +77,7 @@ private:
typedef std::vector<bool> bit_vector;
bool header_codeword(uint64_t acc, uint32_t& nac, uint32_t& duid);
void proc_voice_unit(bit_vector& frame_body) ;
void process_tsbk(uint32_t const nac, uint8_t const tsbk_buf[]);
// internal instance variables and state
int write_bufp;
int write_sock;