dmr group whitelist/blacklist

master
Max 3 years ago
parent 733e891d22
commit 0686f2de14
  1. 8
      op25/gr-op25_repeater/apps/multi_rx.py
  2. 2
      op25/gr-op25_repeater/include/op25_repeater/frame_assembler.h
  3. 50
      op25/gr-op25_repeater/lib/dmr_const.h
  4. 7
      op25/gr-op25_repeater/lib/frame_assembler_impl.cc
  5. 2
      op25/gr-op25_repeater/lib/frame_assembler_impl.h
  6. 173
      op25/gr-op25_repeater/lib/rx_sync.cc
  7. 10
      op25/gr-op25_repeater/lib/rx_sync.h

@ -148,6 +148,14 @@ class channel(object):
self.kill_sink = []
if 'blacklist' in config.keys():
for g in config['blacklist'].split(','):
self.decoder.insert_blacklist(int(g))
if 'whitelist' in config.keys():
for g in config['whitelist'].split(','):
self.decoder.insert_whitelist(int(g))
if 'plot' not in config.keys():
return

@ -51,6 +51,8 @@ namespace gr {
virtual void set_xormask(const char*p) {}
virtual void set_nac(int nac) {}
virtual void set_slotid(int slotid) {}
virtual void insert_whitelist(int grpaddr) {}
virtual void insert_blacklist(int grpaddr) {}
};
} // namespace op25_repeater

@ -21,6 +21,8 @@
#ifndef INCLUDED_OP25_REPEATER_DMR_CONST_H
#define INCLUDED_OP25_REPEATER_DMR_CONST_H
#include <stdint.h>
static const int hamming_7_4[] = {
0, 11, 22, 29, 39, 44, 49, 58,
69, 78, 83, 88, 98, 105, 116, 127,
@ -843,4 +845,52 @@ static const uint8_t dmr_bs_idle_sync[24] = {
static const uint8_t cach_tact_bits[] = {0, 4, 8, 12, 14, 18, 22};
static const uint8_t cach_payload_bits[] = {1,2,3,5,6,7,9,10,11,13,15,16,17,19,20,21,23};
static const uint16_t _pc[] = {0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0};
static const uint32_t slookup_16_11[] = {0, 1, 2, 0, 4, 0, 0, 32, 8, 0, 0, 512, 0, 64, 2048, 0, 16, 0, 0, 32768, 0, 1024, 256, 0, 0, 128, 16384, 0, 4096, 0, 0, 8192};
static const uint32_t masks_16_11[] = {62864, 31432, 15716, 60194, 42721};
static const uint32_t nmasks_16_11 = 5;
static const uint32_t slookup_16_7[] = {0, 1, 2, 3, 4, 5, 6, 0, 8, 9, 10, 0, 12, 0, 0, 32832, 16, 17, 18, 0, 20, 0, 0, 0, 24, 0, 0, 0, 0, 0, 16640, 0, 32, 33, 34, 0, 36, 0, 0, 0, 40, 0, 0, 6144, 0, 0, 0, 0, 48, 0, 0, 576, 0, 0, 0, 0, 0, 0, 0, 0, 33280, 0, 0, 0, 64, 65, 66, 0, 68, 0, 0, 32776, 72, 0, 0, 32772, 0, 32770, 32769, 32768, 80, 0, 0, 544, 0, 12288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32784, 96, 0, 0, 528, 0, 1152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32800, 0, 514, 513, 512, 0, 0, 0, 516, 0, 0, 0, 520, 0, 0, 10240, 0, 128, 129, 130, 0, 132, 0, 0, 0, 136, 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, 0, 0, 0, 1536, 0, 0, 0, 0, 0, 0, 0, 0, 0, 160, 0, 0, 0, 0, 1088, 0, 0, 0, 24576, 33792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8448, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 1056, 0, 0, 0, 2304, 0, 0, 0, 0, 0, 32896, 0, 0, 0, 0, 0, 0, 0, 18432, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1028, 4352, 0, 1025, 1024, 0, 1026, 0, 0, 0, 0, 0, 1032, 0, 0, 0, 0, 0, 640, 0, 1040, 0, 0, 0, 0, 0, 0, 20480, 0, 0, 0, 256, 257, 258, 0, 260, 0, 0, 5120, 264, 0, 0, 0, 0, 0, 16400, 0, 272, 0, 0, 0, 0, 0, 16392, 0, 0, 0, 16388, 0, 16386, 0, 16384, 16385, 288, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3072, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8320, 0, 0, 0, 0, 0, 0, 16416, 0, 320, 0, 0, 0, 0, 0, 0, 0, 0, 2176, 0, 0, 0, 0, 0, 33024, 0, 49152, 9216, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16448, 0, 0, 0, 4224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16896, 0, 0, 0, 0, 0, 768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 384, 0, 0, 0, 0, 0, 34816, 0, 0, 2112, 0, 0, 0, 0, 0, 0, 0, 4608, 0, 0, 0, 0, 0, 8224, 0, 0, 0, 0, 0, 0, 16512, 0, 0, 0, 4160, 0, 0, 0, 0, 8208, 0, 0, 0, 0, 0, 36864, 0, 0, 0, 0, 0, 8196, 0, 8194, 8193, 8192, 0, 0, 2560, 0, 0, 0, 0, 8200, 0, 2056, 4128, 0, 8704, 0, 0, 0, 2049, 2048, 0, 2050, 0, 2052, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2064, 0, 0, 0, 0, 0, 0, 4098, 0, 4096, 4097, 0, 1280, 4100, 0, 0, 2080, 4104, 0, 0, 0, 0, 0, 0, 0, 4112, 0, 0, 0, 0, 8256, 40960, 0, 0, 17408, 0, 0, 0, 0};
static const uint32_t masks_16_7[] = {30976, 15488, 40512, 13856, 25104, 51208, 58372, 61954, 44545};
static const uint32_t nmasks_16_7 = 9;
static const uint32_t slookup_17_12[] = {0, 1, 2, 0, 4, 32, 0, 2048, 8, 0, 64, 0, 0, 256, 4096, 0, 16, 1024, 0, 0, 128, 0, 0, 0, 0, 0, 512, 65536, 8192, 16384, 0, 32768};
static const uint32_t masks_17_12[] = {124560, 127816, 63908, 105026, 118049};
static const uint32_t nmasks_17_12 = 5;
static inline int64_t _hamming_decode(const uint32_t r_codeword, const int n, const int k, const uint32_t *slookup, const uint32_t *masks, const uint32_t nmasks, const int *encode_tab) {
uint32_t syn = 0;
for (uint32_t i=0; i<nmasks; i++) {
uint32_t acc = masks[i] & r_codeword;
uint32_t sum = 0;
for (; acc > 0; acc >>= 8) {
sum += _pc[acc & 0xff];
}
syn = (syn << 1) + (sum & 1);
}
if (syn == 0)
return (r_codeword >> (n - k)); // decode, no error case
uint32_t sl = slookup[syn];
if (sl == 0)
return -1; // decode failed
uint32_t decoded = (r_codeword ^ sl) >> (n - k); // corrected but not yet trusted result
uint32_t encoded = encode_tab[decoded]; // re-encode and verify codewords match
if ((r_codeword ^ sl) == encoded)
return decoded; // decode OK with 1 error corrected
return -2; // decode verification failed
}
static inline int64_t hamming_17_12_decode(const uint32_t r_codeword) {
return _hamming_decode(r_codeword, 17, 12, slookup_17_12, masks_17_12, nmasks_17_12, hamming_17_12);
}
static inline int64_t hamming_16_11_decode(const uint32_t r_codeword) {
return _hamming_decode(r_codeword, 16, 11, slookup_16_11, masks_16_11, nmasks_16_11, hamming_16_11);
}
static inline int64_t hamming_16_7_decode(const uint32_t r_codeword) {
return _hamming_decode(r_codeword, 16, 7, slookup_16_7, masks_16_7, nmasks_16_7, hamming_16_7);
}
#endif /* INCLUDED_OP25_REPEATER_DMR_CONST_H */

@ -46,6 +46,13 @@ namespace gr {
void frame_assembler_impl::set_slotid(int slotid) {
}
void frame_assembler_impl::insert_whitelist(int grpaddr) {
d_sync.insert_whitelist(grpaddr);
}
void frame_assembler_impl::insert_blacklist(int grpaddr) {
d_sync.insert_blacklist(grpaddr);
}
frame_assembler::sptr
frame_assembler::make(const char* options, int debug, gr::msg_queue::sptr queue)
{

@ -50,6 +50,8 @@ namespace gr {
void set_xormask(const char*p) ;
void set_nac(int nac) ;
void set_slotid(int slotid) ;
void insert_whitelist(int grpaddr);
void insert_blacklist(int grpaddr);
public:

@ -132,12 +132,104 @@ void rx_sync::ysf_sync(const uint8_t dibitbuf[], bool& ysf_fullrate, bool& unmut
fprintf(stderr, "ysf_sync: muting audio: dt: %d, rc: %d\n", d_shift_reg, rc);
}
static int decode_embedded(uint8_t result_lc[72], const uint8_t src[32*4], int srclen) {
// return code < 0 indicates decode failure
static const int lengths[] = {11, 11, 10, 10, 10, 10, 10};
int s_index = 0;
uint8_t decode[16*8];
uint8_t decode_lc[72+5];
int srcp = 0;
if (srclen != 32*4)
return -4;
for (int i=0; i<16; i++) {
for (int j=0; j<8; j++){
decode[i+16*j] = src[srcp++];
}
}
for (int i=0; i<7; i++) {
int v = load_i(&decode[16*i], 16);
int rc = hamming_16_11_decode(v);
if (rc < 0)
return rc;
store_i(rc, &decode_lc[11*i], 11);
memcpy(&result_lc[s_index], &decode_lc[11*i], lengths[i]);
s_index += lengths[i];
}
uint16_t r_csum = 0;
for (int i=0; i<5; i++) {
r_csum <<= 1;
r_csum |= decode_lc[(i+2)*11+10] & 1;
}
uint16_t c_csum = 0;
for (int i=0; i<9; i++) {
c_csum += load_i(&result_lc[i*8], 8);
}
c_csum = c_csum % 31;
if (r_csum != c_csum)
return -3;
return 0; // OK return
}
static void init_xlist(int * lp) {
for (int i=0; i < XLIST_SIZE; i++) {
lp[i] = -1;
}
}
static bool find_xlist(const int grp, const int * lp) {
for (int i=0; i < XLIST_SIZE; i++) {
if (lp[i] == grp && grp > 0)
return true;
}
return false;
}
static bool add_xlist(const int grp, int * lp) {
// returns false if failed (grp bad, dup or list full), otherwise true
for (int i=0; i < XLIST_SIZE; i++) {
if (lp[i] == grp || grp < 1)
return false; // dup or group invalid
if (lp[i] == -1) {
lp[i] = grp;
return true;
}
}
return false;
}
static int count_xlist(const int * lp) {
int res=0;
for (int i=0; i < XLIST_SIZE; i++) {
if (lp[i] > 0)
res += 1;
}
return res;
}
void rx_sync::insert_whitelist(int grpaddr) {
bool rc = add_xlist(grpaddr, d_whitelist);
if (rc == false)
fprintf(stderr, "insert_whitelist failed for grp=%d- dup or list full\n", grpaddr);
else if (d_debug)
fprintf(stderr, "insert_whitelist complete for grp=%d\n", grpaddr);
}
void rx_sync::insert_blacklist(int grpaddr) {
bool rc = add_xlist(grpaddr, d_blacklist);
if (rc == false)
fprintf(stderr, "insert_blacklist failed for grp=%d- dup or list full\n", grpaddr);
else if (d_debug)
fprintf(stderr, "insert_blacklist complete for grp=%d\n", grpaddr);
}
void rx_sync::dmr_sync(const uint8_t bitbuf[], int& current_slot, bool& unmute) {
static const int slot_ids[] = {0, 1, 0, 0, 1, 1, 0, 1};
static const uint32_t BURST_SZ = 32; // embedded burst size (bits)
int tact;
int chan;
int fstype;
uint8_t tactbuf[sizeof(cach_tact_bits)];
uint8_t lc72[72];
for (size_t i=0; i<sizeof(cach_tact_bits); i++)
tactbuf[i] = bitbuf[cach_tact_bits[i]];
@ -146,6 +238,9 @@ void rx_sync::dmr_sync(const uint8_t bitbuf[], int& current_slot, bool& unmute)
d_shift_reg = (d_shift_reg << 1) + chan;
current_slot = slot_ids[d_shift_reg & 7];
if (d_groupid_valid[current_slot] > 0)
d_groupid_valid[current_slot] -= 1;
uint64_t sync = load_reg64(bitbuf + (MODE_DATA[RX_TYPE_DMR].sync_offset << 1), MODE_DATA[RX_TYPE_DMR].sync_len);
if (check_frame_sync(DMR_VOICE_SYNC_MAGIC ^ sync, d_threshold, MODE_DATA[RX_TYPE_DMR].sync_len))
fstype = 1;
@ -157,17 +252,83 @@ void rx_sync::dmr_sync(const uint8_t bitbuf[], int& current_slot, bool& unmute)
d_expires = d_symbol_count + MODE_DATA[d_current_type].expiration;
if (fstype == 1) {
if (!d_unmute_until[current_slot] && d_debug > 5)
fprintf(stderr, "unmute slot %d\n", current_slot);
fprintf(stderr, "%d unmute slot %d\n", d_symbol_count, current_slot);
d_unmute_until[current_slot] = d_symbol_count + MODE_DATA[d_current_type].expiration;
} else if (fstype == 2) {
if (d_unmute_until[current_slot] && d_debug > 5)
fprintf(stderr, "mute slot %d\n", current_slot);
fprintf(stderr, "%d mute slot %d\n", d_symbol_count, current_slot);
d_unmute_until[current_slot] = 0;
}
if (d_unmute_until[current_slot] <= d_symbol_count) {
d_unmute_until[current_slot] = 0;
}
unmute = d_unmute_until[current_slot] > 0;
if (fstype == 0) {
uint16_t emb = (load_i(bitbuf+132, 8) << 8) + load_i(bitbuf+172, 8);
int emb_decode = hamming_16_7_decode(emb);
if (emb_decode >= 0) {
uint8_t cc = emb_decode >> 3;
uint8_t pi = (emb_decode >> 2) & 1;
uint8_t lcss = emb_decode & 3;
switch (lcss) {
case 0:
break;
case 1:
memcpy(d_burstb[current_slot], bitbuf+140, BURST_SZ);
d_burstl[current_slot] = BURST_SZ;
break;
case 2:
if (d_burstl[current_slot] && d_burstl[current_slot]+BURST_SZ <= sizeof(d_burstb)) {
memcpy(d_burstb[current_slot] + d_burstl[current_slot], bitbuf+140, BURST_SZ);
d_burstl[current_slot] += BURST_SZ;
int rc = decode_embedded(lc72, d_burstb[current_slot], d_burstl[current_slot]);
if (rc >= 0) {
int opcode = load_i(lc72+2, 6);
if (opcode == 0) { // group voice channel user
int grpaddr = load_i(lc72+24, 24);
if (grpaddr > 0) {
d_groupid[current_slot] = grpaddr;
d_groupid_valid[current_slot] = 20;
}
}
} else {
if (d_debug)
fprintf(stderr, "decode_embedded failed, code %d\n", rc);
}
}
d_burstl[current_slot] = 0;
break;
case 3:
if (d_burstl[current_slot] && d_burstl[current_slot]+BURST_SZ <= sizeof(d_burstb)) {
memcpy(d_burstb[current_slot] + d_burstl[current_slot], bitbuf+140, BURST_SZ);
d_burstl[current_slot] += BURST_SZ;
} else {
d_burstl[current_slot] = 0;
}
break;
}
} else {
d_burstl[current_slot] = 0;
}
}
if (unmute && d_groupid_valid[current_slot] > 0) {
if (count_xlist(d_whitelist) > 0 && !find_xlist(d_groupid[current_slot], d_whitelist)) {
if (d_debug)
fprintf(stderr, "%d group %d not in whitelist, muting slot %d\n", d_symbol_count, d_groupid[current_slot], current_slot);
unmute = 0;
if (d_unmute_until[current_slot] && d_debug > 5)
fprintf(stderr, "%d mute slot %d\n", d_symbol_count, current_slot);
d_unmute_until[current_slot] = 0;
}
if (count_xlist(d_blacklist) > 0 && find_xlist(d_groupid[current_slot], d_blacklist)) {
if (d_debug)
fprintf(stderr, "group %d in blacklist, muting slot %d\n", d_groupid[current_slot], current_slot);
unmute = 0;
if (d_unmute_until[current_slot] && d_debug > 5)
fprintf(stderr, "%d mute slot %d\n", d_symbol_count, current_slot);
d_unmute_until[current_slot] = 0;
}
}
}
rx_sync::rx_sync(const char * options, int debug) : // constructor
@ -184,6 +345,14 @@ rx_sync::rx_sync(const char * options, int debug) : // constructor
mbe_initMbeParms (&cur_mp[0], &prev_mp[0], &enh_mp[0]);
mbe_initMbeParms (&cur_mp[1], &prev_mp[1], &enh_mp[1]);
sync_reset();
d_burstl[0] = 0;
d_burstl[1] = 0;
init_xlist(d_whitelist);
init_xlist(d_blacklist);
d_groupid[0] = 0;
d_groupid_valid[0] = 0;
d_groupid[1] = 0;
d_groupid_valid[1] = 0;
}
rx_sync::~rx_sync() // destructor

@ -88,12 +88,16 @@ enum codeword_types {
CODEWORD_NXDN_EHR
};
#define XLIST_SIZE 256
class rx_sync {
public:
void rx_sym(const uint8_t sym);
void sync_reset(void);
rx_sync(const char * options, int debug);
~rx_sync();
void insert_whitelist(int grpaddr);
void insert_blacklist(int grpaddr);
private:
void cbuf_insert(const uint8_t c);
void dmr_sync(const uint8_t bitbuf[], int& current_slot, bool& unmute);
@ -122,6 +126,12 @@ private:
bool d_stereo;
int d_debug;
op25_audio d_audio;
uint8_t d_burstb[2][32*4];
int d_burstl[2]; // in units of bits
int d_groupid[2];
unsigned int d_groupid_valid[2];
int d_whitelist[XLIST_SIZE];
int d_blacklist[XLIST_SIZE];
};
} // end namespace op25_repeater

Loading…
Cancel
Save