op25/op25/gr-op25_repeater/lib/p25p2_tdma.cc

117 lines
3.2 KiB
C++

// P25 TDMA Decoder (C) Copyright 2013, 2014 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 <stdint.h>
#include <map>
#include <string.h>
#include <string>
#include <iostream>
#include <assert.h>
#include "p25p2_duid.h"
#include "p25p2_sync.h"
#include "p25p2_tdma.h"
#include "p25p2_vf.h"
#include "mbelib.h"
#include "ambe.h"
static const int BURST_SIZE = 180;
static const int SUPERFRAME_SIZE = (12*BURST_SIZE);
p25p2_tdma::p25p2_tdma(int slotid, std::deque<int16_t> *qptr) : // constructor
tdma_xormask(new uint8_t[SUPERFRAME_SIZE]),
packets(0),
d_slotid(slotid),
output_queue_decode(qptr)
{
assert (slotid == 0 || slotid == 1);
mbe_initMbeParms (&cur_mp, &prev_mp, &enh_mp);
}
void p25p2_tdma::set_slotid(int slotid)
{
assert (slotid == 0 || slotid == 1);
d_slotid = slotid;
}
p25p2_tdma::~p25p2_tdma() // destructor
{
delete[](tdma_xormask);
}
void
p25p2_tdma::set_xormask(const char*p) {
for (int i=0; i<SUPERFRAME_SIZE; i++)
tdma_xormask[i] = p[i] & 3;
}
void p25p2_tdma::handle_voice_frame(const uint8_t dibits[])
{
static const int NSAMP_OUTPUT=160;
int b[9];
int16_t snd;
int K;
int rc = -1;
vf.process_vcw(dibits, b);
if (b[0] < 120)
rc = mbe_dequantizeAmbe2250Parms (&cur_mp, &prev_mp, b);
/* FIXME: check RC */
K = 12;
if (cur_mp.L <= 36)
K = int(float(cur_mp.L + 2.0) / 3.0);
if (rc == 0)
software_decoder.decode_tap(cur_mp.L, K, cur_mp.w0, &cur_mp.Vl[1], &cur_mp.Ml[1]);
audio_samples *samples = software_decoder.audio();
for (int i=0; i < NSAMP_OUTPUT; i++) {
if (samples->size() > 0) {
snd = (int16_t)(samples->front());
samples->pop_front();
} else {
snd = 0;
}
output_queue_decode->push_back(snd);
}
mbe_moveMbeParms (&cur_mp, &prev_mp);
mbe_moveMbeParms (&cur_mp, &enh_mp);
}
void p25p2_tdma::handle_packet(const uint8_t dibits[])
{
static const int which_slot[] = {0,1,0,1,0,1,0,1,0,1,1,0};
packets++;
sync.check_confidence(dibits);
if (!sync.in_sync())
return;
const uint8_t* burstp = &dibits[10];
uint8_t xored_burst[170];
int burst_type = duid.duid_lookup(duid.extract_duid(burstp));
if (which_slot[sync.tdma_slotid()] == d_slotid && (burst_type == 0 || burst_type == 6)) { // 4v or 2v (voice) ?
for (int i=0; i<170; i++) {
xored_burst[i] = burstp[i] ^ tdma_xormask[sync.tdma_slotid() * BURST_SIZE + i];
}
handle_voice_frame(&xored_burst[11]);
handle_voice_frame(&xored_burst[48]);
if (burst_type == 0) { // 4v ?
handle_voice_frame(&xored_burst[96]);
handle_voice_frame(&xored_burst[133]);
}
}
}