mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-12 16:57:23 -05:00
NXDN -- Implement Secondary 1/2 Decoder; Misc;
This commit is contained in:
@@ -1032,6 +1032,8 @@ void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[2
|
||||
//end
|
||||
void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType);
|
||||
void nxdn_voice (dsd_opts * opts, dsd_state * state, int voice, uint8_t dbuf[182]);
|
||||
//Osmocom OP25 12 Rate Trellis Decoder (for NXDN, M17, YSF, etc)
|
||||
void trellis_decode(uint8_t result[], const uint8_t source[], int result_len);
|
||||
|
||||
//OP25 NXDN CRC functions
|
||||
int load_i(const uint8_t val[], int len);
|
||||
|
||||
82
src/3.c
82
src/3.c
@@ -2,6 +2,86 @@
|
||||
* 3.c
|
||||
* Placeholder File 3 -- This file is for temporary code storage
|
||||
*
|
||||
* A 1/2 Rate Convolutional Decoder for NXDN/M17/YSF
|
||||
* Used as a secondary decoder in case convolutional decoder fails (second opinion)
|
||||
*-----------------------------------------------------------------------------*/
|
||||
|
||||
#include "dsd.h"
|
||||
|
||||
static const int PARITY[] = {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};
|
||||
|
||||
// trellis_1_2 encode: source is in bits, result in bits
|
||||
void trellis_encode(uint8_t result[], const uint8_t source[], int result_len, int reg)
|
||||
{
|
||||
for (int i=0; i<result_len; i+=2) {
|
||||
reg = (reg << 1) | source[i>>1];
|
||||
result[i] = PARITY[reg & 0x19];
|
||||
result[i+1] = PARITY[reg & 0x17];
|
||||
}
|
||||
}
|
||||
|
||||
// simplified trellis 2:1 decode; source and result in bits
|
||||
// assumes that encoding was done with NTEST trailing zero bits
|
||||
// result_len should be set to the actual number of data bits
|
||||
// in the original unencoded message (excl. these trailing bits)
|
||||
void trellis_decode(uint8_t result[], const uint8_t source[], int result_len)
|
||||
{
|
||||
int reg = 0;
|
||||
int min_d;
|
||||
int min_bt;
|
||||
static const int NTEST = 4;
|
||||
static const int NTESTC = 1 << NTEST;
|
||||
uint8_t bt[NTEST];
|
||||
uint8_t tt[NTEST*2];
|
||||
int dstats[4];
|
||||
int sum;
|
||||
for (int p=0; p < 4; p++)
|
||||
dstats[p] = 0;
|
||||
for (int p=0; p < result_len; p++) {
|
||||
for (int i=0; i<NTESTC; i++) {
|
||||
bt[0] = (i&8)>>3;
|
||||
bt[1] = (i&4)>>2;
|
||||
bt[2] = (i&2)>>1;
|
||||
bt[3] = (i&1);
|
||||
trellis_encode(tt, bt, NTEST*2, reg);
|
||||
sum=0;
|
||||
for (int j=0; j<NTEST*2; j++) {
|
||||
sum += tt[j] ^ source[p*2+j];
|
||||
}
|
||||
if (i == 0 || sum < min_d) {
|
||||
min_d = sum;
|
||||
min_bt = bt[0];
|
||||
}
|
||||
}
|
||||
result[p] = min_bt;
|
||||
reg = (reg << 1) | min_bt;
|
||||
dstats[(min_d > 3) ? 3 : min_d] += 1;
|
||||
}
|
||||
|
||||
//debug output
|
||||
// fprintf (stderr, "\n stats\t%d %d %d %d\n", dstats[0], dstats[1], dstats[2], dstats[3]);
|
||||
}
|
||||
|
||||
//Original Copyright/License
|
||||
|
||||
/* -*- c++ -*- */
|
||||
/*
|
||||
* NXDN Encoder/Decoder (C) Copyright 2019 Max H. Parke KA1RBI
|
||||
*
|
||||
* This file is part of OP25
|
||||
*
|
||||
*-----------------------------------------------------------------------------*/
|
||||
* This 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.
|
||||
*
|
||||
* This software 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 this software; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
@@ -52,7 +52,7 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
|
||||
uint8_t deperm[144]; //144
|
||||
uint8_t depunc[192]; //192
|
||||
uint8_t trellis_buf[96]; //96
|
||||
uint16_t crc = 0; //crc calculated by function
|
||||
uint16_t crc = 1; //crc calculated by function
|
||||
uint16_t check = 0; //crc from payload for comparison
|
||||
int out;
|
||||
|
||||
@@ -111,6 +111,30 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
|
||||
check = check | trellis_buf[84+i]; //80
|
||||
}
|
||||
|
||||
//debug
|
||||
// if (crc == check)
|
||||
// fprintf (stderr, " Pass 1 ");
|
||||
|
||||
//if the crc fails, attempt again with the other trellis decoder
|
||||
if (crc != check)
|
||||
{
|
||||
//debug
|
||||
// fprintf (stderr, " Pass 2 ");
|
||||
crc = 1; check = 0;
|
||||
memset (trellis_buf, 0, sizeof(trellis_buf));
|
||||
memset (m_data, 0, sizeof(m_data));
|
||||
trellis_decode(trellis_buf, depunc, 92);
|
||||
//fill m_data bytes with trellis_buf
|
||||
for(int i = 0; i < 12; i++)
|
||||
m_data[i] = (uint8_t)ConvertBitIntoBytes(&trellis_buf[i*8], 8);
|
||||
crc = crc12f (trellis_buf, 84);
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
check = check << 1;
|
||||
check = check | trellis_buf[i+84];
|
||||
}
|
||||
}
|
||||
|
||||
if (crc == check) NXDN_Elements_Content_decode(opts, state, 1, trellis_buf);
|
||||
// else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, trellis_buf);
|
||||
|
||||
@@ -145,7 +169,7 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
|
||||
memset (trellis_buf, 0, sizeof(trellis_buf));
|
||||
|
||||
int o = 0;
|
||||
uint8_t crc = 0; //value computed by crc6 on payload
|
||||
uint8_t crc = 1; //value computed by crc6 on payload
|
||||
uint8_t check = 0; //value pulled from last 6 bits
|
||||
int sf = 0;
|
||||
int ran = 0;
|
||||
@@ -212,6 +236,30 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
|
||||
check = check | trellis_buf[i+26];
|
||||
}
|
||||
|
||||
//debug
|
||||
// if (crc == check)
|
||||
// fprintf (stderr, " Pass 1 ");
|
||||
|
||||
//if the crc fails, attempt again with the other trellis decoder
|
||||
if (crc != check)
|
||||
{
|
||||
//debug
|
||||
// fprintf (stderr, " Pass 2 ");
|
||||
crc = 1; check = 0;
|
||||
memset (trellis_buf, 0, sizeof(trellis_buf));
|
||||
memset (m_data, 0, sizeof(m_data));
|
||||
trellis_decode(trellis_buf, depunc, 32);
|
||||
//fill m_data bytes with trellis_buf
|
||||
for(int i = 0; i < 4; i++)
|
||||
m_data[i] = (uint8_t)ConvertBitIntoBytes(&trellis_buf[i*8], 8);
|
||||
crc = crc6(trellis_buf, 26); //32
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
check = check << 1;
|
||||
check = check | trellis_buf[i+26];
|
||||
}
|
||||
}
|
||||
|
||||
//FIRST! If part of a non_superframe, and CRC is good, send directly to NXDN_Elements_Content_decode
|
||||
if (state->nxdn_sacch_non_superframe == TRUE)
|
||||
{
|
||||
@@ -284,12 +332,12 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
|
||||
|
||||
fprintf (stderr, "PF %d/4", part_of_frame+1);
|
||||
|
||||
if (crc != check)
|
||||
{
|
||||
fprintf (stderr, "%s", KRED);
|
||||
fprintf (stderr, " (CRC ERR)");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
// if (crc != check)
|
||||
// {
|
||||
// fprintf (stderr, "%s", KRED);
|
||||
// fprintf (stderr, " (CRC ERR)");
|
||||
// fprintf (stderr, "%s", KNRM);
|
||||
// }
|
||||
|
||||
//reset scrambler seed to key value on new superframe
|
||||
if (part_of_frame == 0 && state->nxdn_cipher_type == 0x1) state->payload_miN = 0;
|
||||
@@ -319,16 +367,16 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
|
||||
NXDN_SACCH_Full_decode (opts, state);
|
||||
}
|
||||
|
||||
// if (opts->payload == 1)
|
||||
// {
|
||||
// fprintf (stderr, "\n");
|
||||
// fprintf (stderr, " SACCH SF Segment #%d ", part_of_frame+1);
|
||||
// for (int i = 0; i < 4; i++)
|
||||
// {
|
||||
// fprintf (stderr, "[%02X]", m_data[i]);
|
||||
// }
|
||||
// // if (crc != check) fprintf (stderr, " CRC ERR - %02X %02X", crc, check);
|
||||
// }
|
||||
if (opts->payload == 1)
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " SACCH SF Segment #%d ", part_of_frame+1);
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
fprintf (stderr, "[%02X]", m_data[i]);
|
||||
}
|
||||
if (crc != check) fprintf (stderr, " CRC ERR - %02X %02X", crc, check);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user