// P25 Decoder (C) Copyright 2013, 2014, 2015, 2016, 2017 Max H. Parke KA1RBI // // This file is part of OP25 // // OP25 is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3, or (at your option) // any later version. // // OP25 is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public // License for more details. // // You should have received a copy of the GNU General Public License // along with OP25; see the file COPYING. If not, write to the Free // Software Foundation, Inc., 51 Franklin Street, Boston, MA // 02110-1301, USA. #include #include #include #include #include #include #include #include #include #include #include "rx_sync.h" #include "bit_utils.h" #include "check_frame_sync.h" #include "p25p2_vf.h" #include "mbelib.h" #include "ambe.h" #include "rs.h" #include "crc16.h" #include "ysf_const.h" #include "dmr_const.h" #include "p25_frame.h" #include "op25_imbe_frame.h" #include "software_imbe_decoder.h" #include "op25_audio.h" namespace gr{ namespace op25_repeater{ void rx_sync::cbuf_insert(const uint8_t c) { d_cbuf[d_cbuf_idx] = c; d_cbuf[d_cbuf_idx + CBUF_SIZE] = c; d_cbuf_idx = (d_cbuf_idx + 1) % CBUF_SIZE; } void rx_sync::sync_reset(void) { d_threshold = 0; d_shift_reg = 0; d_unmute_until[0] = 0; d_unmute_until[1] = 0; } static int ysf_decode_fich(const uint8_t src[100], uint8_t dest[32]) { // input is 100 dibits, result is 32 bits // return -1 on decode error, else 0 static const int 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}; uint8_t buf[100]; for (int i=0; i<20; i++) { for (int j=0; j<5; j++) { buf[j+i*5] = src[i+j*20]; } } uint8_t dr = 0; uint8_t ans[100]; /* fake trellis decode */ /* TODO: make less fake */ for (int i=0; i<100; i++) { uint8_t sym = buf[i]; uint8_t d0 = ((dr << 1) | 0) & 0x1f; uint8_t r0 = (pc[ d0 & 0x19 ] << 1) + pc[ d0 & 0x17]; uint8_t d1 = ((dr << 1) | 1) & 0x1f; uint8_t r1 = (pc[ d1 & 0x19 ] << 1) + pc[ d1 & 0x17]; if (sym == r0) { ans[i] = 0; dr = d0; } else if (sym == r1) { ans[i] = 1; dr = d1; } else { return -1; /* decode error */ } } uint8_t fich_bits[12*4]; store_i(gly24128Dec(load_i(ans+24*0, 24)), fich_bits+12*0, 12); store_i(gly24128Dec(load_i(ans+24*1, 24)), fich_bits+12*1, 12); store_i(gly24128Dec(load_i(ans+24*2, 24)), fich_bits+12*2, 12); store_i(gly24128Dec(load_i(ans+24*3, 24)), fich_bits+12*3, 12); uint16_t crc_result = crc16(fich_bits, 48); if (crc_result != 0) return -1; // crc failure memcpy(dest, fich_bits, 32); return 0; } void rx_sync::ysf_sync(const uint8_t dibitbuf[], bool& ysf_fullrate, bool& unmute) { uint8_t fich_buf[32]; int rc = ysf_decode_fich(dibitbuf+20, fich_buf); if (rc == 0) { uint32_t fich = load_i(fich_buf, 32); uint32_t dt = (fich >> 8) & 3; d_shift_reg = dt; } switch(d_shift_reg) { case 0: // voice/data mode 1 unmute = false; break; case 1: // data mode unmute = false; break; case 2: // voice/data mode 2 unmute = true; ysf_fullrate = false; break; case 3: // voice fr mode unmute = true; ysf_fullrate = true; break; } if (d_debug > 5 && !unmute) fprintf(stderr, "ysf_sync: muting audio: dt: %d, rc: %d\n", d_shift_reg, rc); } 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}; int tact; int chan; int fstype; uint8_t tactbuf[sizeof(cach_tact_bits)]; for (size_t i=0; i>2) & 1; d_shift_reg = (d_shift_reg << 1) + chan; current_slot = slot_ids[d_shift_reg & 7]; 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; else if (check_frame_sync(DMR_IDLE_SYNC_MAGIC ^ sync, d_threshold, MODE_DATA[RX_TYPE_DMR].sync_len)) fstype = 2; else fstype = 0; if (fstype > 0) 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); 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); 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; } rx_sync::rx_sync(const char * options, int debug) : // constructor d_symbol_count(0), d_sync_reg(0), d_cbuf_idx(0), d_current_type(RX_TYPE_NONE), d_rx_count(0), d_expires(0), d_stereo(false), d_debug(debug), d_audio(options, debug) { mbe_initMbeParms (&cur_mp[0], &prev_mp[0], &enh_mp[0]); mbe_initMbeParms (&cur_mp[1], &prev_mp[1], &enh_mp[1]); sync_reset(); } rx_sync::~rx_sync() // destructor { } void rx_sync::codeword(const uint8_t* cw, const enum codeword_types codeword_type, int slot_id) { static const int x=4; static const int y=26; static const uint8_t majority[8] = {0,0,0,1,0,1,1,1}; int b[9]; uint8_t buf[4*26]; uint8_t tmp_codeword [144]; uint32_t E0, ET; uint32_t u[8]; bool do_fullrate = false; bool do_silence = false; voice_codeword fullrate_cw(voice_codeword_sz); switch(codeword_type) { case CODEWORD_DMR: interleaver.process_vcw(cw, b); if (b[0] < 120) mbe_dequantizeAmbe2250Parms(&cur_mp[slot_id], &prev_mp[slot_id], b); break; case CODEWORD_DSTAR: interleaver.decode_dstar(cw, b, false); if (b[0] < 120) mbe_dequantizeAmbe2400Parms(&cur_mp[slot_id], &prev_mp[slot_id], b); break; case CODEWORD_YSF_HALFRATE: // 104 bits for (int i=0; i= 120) { do_silence = true; } else { d_software_decoder[slot_id].decode_tap(cur_mp[slot_id].L, 0, cur_mp[slot_id].w0, &cur_mp[slot_id].Vl[1], &cur_mp[slot_id].Ml[1]); } } audio_samples *samples = d_software_decoder[slot_id].audio(); float snd; int16_t samp_buf[NSAMP_OUTPUT]; for (int i=0; i < NSAMP_OUTPUT; i++) { if ((!do_silence) && samples->size() > 0) { snd = samples->front(); samples->pop_front(); } else { snd = 0; } if (do_fullrate) snd *= 32768.0; samp_buf[i] = snd; } output(samp_buf, slot_id); } void rx_sync::output(int16_t * samp_buf, const ssize_t slot_id) { if (!d_stereo) { d_audio.send_audio_channel(samp_buf, NSAMP_OUTPUT * sizeof(int16_t), slot_id); return; } } void rx_sync::rx_sym(const uint8_t sym) { uint8_t bitbuf[864*2]; enum rx_types sync_detected = RX_TYPE_NONE; int current_slot; bool unmute; uint8_t tmpcw[144]; bool ysf_fullrate; d_symbol_count ++; d_sync_reg = (d_sync_reg << 2) | (sym & 3); for (int i = 1; i < RX_N_TYPES; i++) { if (check_frame_sync(MODE_DATA[i].sync ^ d_sync_reg, (i == d_current_type) ? d_threshold : 0, MODE_DATA[i].sync_len)) { sync_detected = (enum rx_types) i; break; } } cbuf_insert(sym); if (d_current_type == RX_TYPE_NONE && sync_detected == RX_TYPE_NONE) return; d_rx_count ++; if (sync_detected != RX_TYPE_NONE) { if (d_current_type != sync_detected) { d_current_type = sync_detected; d_expires = d_symbol_count + MODE_DATA[d_current_type].expiration; d_rx_count = 0; } if (d_rx_count != MODE_DATA[d_current_type].sync_offset + (MODE_DATA[d_current_type].sync_len >> 1)) { if (d_debug) fprintf(stderr, "resync at count %d for protocol %s\n", d_rx_count, MODE_DATA[d_current_type].type); sync_reset(); d_rx_count = MODE_DATA[d_current_type].sync_offset + (MODE_DATA[d_current_type].sync_len >> 1); } else { d_threshold = std::min(d_threshold + 1, 2); } d_expires = d_symbol_count + MODE_DATA[d_current_type].expiration; } if (d_symbol_count >= d_expires) { if (d_debug) fprintf(stderr, "%s: timeout, symbol %d\n", MODE_DATA[d_current_type].type, d_symbol_count); d_current_type = RX_TYPE_NONE; return; } if (d_rx_count < MODE_DATA[d_current_type].fragment_len) return; d_rx_count = 0; int start_idx = d_cbuf_idx + CBUF_SIZE - MODE_DATA[d_current_type].fragment_len; assert (start_idx >= 0); uint8_t * symbol_ptr = d_cbuf+start_idx; uint8_t * bit_ptr = symbol_ptr; if (d_current_type != RX_TYPE_DSTAR) { dibits_to_bits(bitbuf, symbol_ptr, MODE_DATA[d_current_type].fragment_len); bit_ptr = bitbuf; } switch (d_current_type) { case RX_TYPE_NONE: break; case RX_TYPE_P25: for (unsigned int codeword_ct=0; codeword_ct < nof_voice_codewords; codeword_ct++) { for (unsigned int i=0; i