mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-24 19:00:36 -05:00
DSDplus library: interim state #1
This commit is contained in:
parent
0b58a50ee8
commit
dd39afdc64
@ -17,11 +17,55 @@
|
||||
#include "dmr_voice.h"
|
||||
#include "dsd_decoder.h"
|
||||
|
||||
namespace DSDPlus
|
||||
namespace DSDplus
|
||||
{
|
||||
|
||||
/*
|
||||
* DMR AMBE interleave schedule
|
||||
*/
|
||||
const int DSDDMRVoice::rW[36] = {
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 2,
|
||||
0, 2, 0, 2, 0, 2,
|
||||
0, 2, 0, 2, 0, 2
|
||||
};
|
||||
|
||||
const int DSDDMRVoice::rX[36] = {
|
||||
23, 10, 22, 9, 21, 8,
|
||||
20, 7, 19, 6, 18, 5,
|
||||
17, 4, 16, 3, 15, 2,
|
||||
14, 1, 13, 0, 12, 10,
|
||||
11, 9, 10, 8, 9, 7,
|
||||
8, 6, 7, 5, 6, 4
|
||||
};
|
||||
|
||||
const int DSDDMRVoice::rY[36] = {
|
||||
0, 2, 0, 2, 0, 2,
|
||||
0, 2, 0, 3, 0, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3
|
||||
};
|
||||
|
||||
const int DSDDMRVoice::rZ[36] = {
|
||||
5, 3, 4, 2, 3, 1,
|
||||
2, 0, 1, 13, 0, 12,
|
||||
22, 11, 21, 10, 20, 9,
|
||||
19, 8, 18, 7, 17, 6,
|
||||
16, 5, 15, 4, 14, 3,
|
||||
13, 2, 12, 1, 11, 0
|
||||
};
|
||||
|
||||
|
||||
DSDDMRVoice::DSDDMRVoice(DSDDecoder *dsdDecoder) :
|
||||
m_dsdDecoder(dsdDecoder)
|
||||
m_dsdDecoder(dsdDecoder),
|
||||
m_symbolIndex(0),
|
||||
m_dibitIndex(0),
|
||||
mutecurrentslot(0),
|
||||
m_slotIndex(-1)
|
||||
{
|
||||
}
|
||||
|
||||
@ -34,13 +78,307 @@ void DSDDMRVoice::init()
|
||||
mutecurrentslot = 0;
|
||||
msMode = 0;
|
||||
dibit_p = m_dsdDecoder->m_state.dibit_buf_p - 144;
|
||||
m_slotIndex = 0;
|
||||
m_majorBlock = 0;
|
||||
m_symbolIndex = 0;
|
||||
|
||||
preProcess();
|
||||
|
||||
m_symbolIndex = 144; // reposition symbol index in frame
|
||||
}
|
||||
|
||||
void DSDDMRVoice::process()
|
||||
{
|
||||
m_majorBlock = m_symbolIndex / 288; // frame (major block) index
|
||||
m_dibitIndex = m_symbolIndex % 288; // index of symbol in frame
|
||||
int symbolIndex = getSlotIndex(m_dibitIndex); // returns symbol index in current slot. Updates m_slotIndex.
|
||||
|
||||
switch(m_slotIndex)
|
||||
{
|
||||
case 0:
|
||||
processSlot0(symbolIndex);
|
||||
break;
|
||||
case 1:
|
||||
processSlot1(symbolIndex);
|
||||
break;
|
||||
case 2:
|
||||
processSlot2(symbolIndex);
|
||||
break;
|
||||
case 3:
|
||||
processSlot3(symbolIndex);
|
||||
break;
|
||||
case 4:
|
||||
processSlot4(symbolIndex);
|
||||
break;
|
||||
case 5:
|
||||
processSlot5(symbolIndex);
|
||||
break;
|
||||
case 6:
|
||||
processSlot6(symbolIndex);
|
||||
break;
|
||||
case 7:
|
||||
processSlot7(symbolIndex);
|
||||
break;
|
||||
case 8:
|
||||
processSlot8(symbolIndex);
|
||||
break;
|
||||
case 9:
|
||||
processSlot9(symbolIndex);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_symbolIndex++;
|
||||
}
|
||||
|
||||
void DSDDMRVoice::preProcess()
|
||||
{
|
||||
// copy in memory to dibit cache
|
||||
memcpy((void *) m_dibitCache, (const void *) dibit_p, 144 * sizeof(int));
|
||||
|
||||
m_dibitIndex = 54-1; // set cache pointer - skip slot 0
|
||||
|
||||
m_dibitIndex += 12; // advance cache pointer
|
||||
processSlot1(12-1);
|
||||
|
||||
m_dibitIndex += 36; // advance cache pointer
|
||||
processSlot2(36-1);
|
||||
|
||||
m_dibitIndex += 18; // advance cache pointer
|
||||
processSlot3(18-1);
|
||||
|
||||
m_dibitIndex += 24; // advance cache pointer
|
||||
processSlot4(24-1);
|
||||
|
||||
m_dibitIndex += 18; // advance cache pointer
|
||||
processSlot5(18-1);
|
||||
|
||||
m_dibitIndex += 36; // advance cache pointer
|
||||
processSlot6(36-1);
|
||||
|
||||
m_dibitIndex += 12; // advance cache pointer
|
||||
processSlot7(12-1);
|
||||
|
||||
m_dibitIndex += 54; // advance cache pointer - skip slot 8
|
||||
|
||||
processSlot9(24-1);
|
||||
m_dibitIndex += 24; // advance cache pointer
|
||||
processSlot9(24-1);
|
||||
|
||||
m_symbolIndex = 144; // advance the main symbol index
|
||||
}
|
||||
|
||||
void DSDDMRVoice::processSlot0(int symbolIndex) // Slot0 is a 54 symbol slot
|
||||
{
|
||||
m_dsdDecoder->getDibit(); // get dibit from symbol but do nothing with it
|
||||
}
|
||||
|
||||
void DSDDMRVoice::processSlot8(int symbolIndex) // Slot8 is a 54 symbol slot
|
||||
{
|
||||
m_dsdDecoder->getDibit(); // get dibit from symbol but do nothing with it
|
||||
}
|
||||
|
||||
void DSDDMRVoice::processSlot1(int symbolIndex) // Slot1 is a 12 symbol slot
|
||||
{
|
||||
if (m_majorBlock > 0) // 0:1 reads from 144 in memory dibits. Handled by upper layer.
|
||||
{
|
||||
int dibit = m_dsdDecoder->getDibit(); // get dibit from symbol and store it in cache
|
||||
m_dibitCache[m_dibitIndex] = dibit;
|
||||
}
|
||||
|
||||
if (symbolIndex == 12-1) // last symbol -> launch process
|
||||
{
|
||||
int *dibitCache = &m_dibitCache[m_dibitIndex - symbolIndex]; // move back to start of corresponding cache section
|
||||
// CACH
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
int dibit = dibitCache[i];
|
||||
cachdata[i] = dibit;
|
||||
|
||||
if (i == 2)
|
||||
{
|
||||
m_dsdDecoder->m_state.currentslot = (1 & (dibit >> 1)); // bit 1
|
||||
|
||||
if (m_dsdDecoder->m_state.currentslot == 0)
|
||||
{
|
||||
m_dsdDecoder->m_state.slot0light[0] = '[';
|
||||
m_dsdDecoder->m_state.slot0light[6] = ']';
|
||||
m_dsdDecoder->m_state.slot1light[0] = ' ';
|
||||
m_dsdDecoder->m_state.slot1light[6] = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dsdDecoder->m_state.slot1light[0] = '[';
|
||||
m_dsdDecoder->m_state.slot1light[6] = ']';
|
||||
m_dsdDecoder->m_state.slot0light[0] = ' ';
|
||||
m_dsdDecoder->m_state.slot0light[6] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cachdata[12] = 0;
|
||||
m_dibitIndex = 0; // done with the cache -> reset index
|
||||
}
|
||||
}
|
||||
|
||||
void DSDDMRVoice::processSlot2(int symbolIndex) // Slot2 is a 36 symbol slot
|
||||
{
|
||||
if (m_majorBlock > 0) // 0:2 reads from 144 in memory dibits. Handled by upper layer.
|
||||
{
|
||||
int dibit = m_dsdDecoder->getDibit(); // get dibit from symbol and store it in cache
|
||||
m_dibitCache[m_dibitIndex] = dibit;
|
||||
}
|
||||
|
||||
if (symbolIndex == 36-1) // last symbol -> launch process
|
||||
{
|
||||
int *dibitCache = &m_dibitCache[m_dibitIndex - symbolIndex]; // move back to start of corresponding cache section
|
||||
|
||||
w = rW;
|
||||
x = rX;
|
||||
y = rY;
|
||||
z = rZ;
|
||||
|
||||
for (int i = 0; i < 36; i++)
|
||||
{
|
||||
int dibit = dibitCache[i];
|
||||
|
||||
ambe_fr[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||
ambe_fr[*y][*z] = (1 & dibit); // bit 0
|
||||
w++;
|
||||
x++;
|
||||
y++;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSDDMRVoice::processSlot3(int symbolIndex) // Slot3 is a 18 symbol slot
|
||||
{
|
||||
if (m_majorBlock > 0) // 0:3 reads from 144 in memory dibits. Handled by upper layer.
|
||||
{
|
||||
int dibit = m_dsdDecoder->getDibit(); // get dibit from symbol and store it in cache
|
||||
m_dibitCache[m_dibitIndex] = dibit;
|
||||
}
|
||||
|
||||
if (symbolIndex == 18-1) // last symbol -> launch process
|
||||
{
|
||||
int *dibitCache = &m_dibitCache[m_dibitIndex - symbolIndex]; // move back to start of corresponding cache section
|
||||
|
||||
w = rW;
|
||||
x = rX;
|
||||
y = rY;
|
||||
z = rZ;
|
||||
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
int dibit = dibitCache[i];
|
||||
|
||||
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
|
||||
w++;
|
||||
x++;
|
||||
y++;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSDDMRVoice::processSlot4(int symbolIndex) // Slot4 is a 24 symbol slot
|
||||
{
|
||||
if (m_majorBlock > 0) // 0:3 reads from 144 in memory dibits. Handled by upper layer.
|
||||
{
|
||||
int dibit = m_dsdDecoder->getDibit(); // get dibit from symbol and store it in cache
|
||||
m_dibitCache[m_dibitIndex] = dibit;
|
||||
}
|
||||
|
||||
if (symbolIndex == 24-1) // last symbol -> launch process
|
||||
{
|
||||
int *dibitCache = &m_dibitCache[m_dibitIndex - symbolIndex]; // move back to start of corresponding cache section
|
||||
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
int dibit = dibitCache[i];
|
||||
|
||||
syncdata[i] = dibit;
|
||||
sync[i] = (dibit | 1) + 48;
|
||||
}
|
||||
|
||||
sync[24] = 0;
|
||||
syncdata[24] = 0;
|
||||
|
||||
if ((strcmp(sync, DMR_BS_DATA_SYNC) == 0)
|
||||
|| (strcmp(sync, DMR_MS_DATA_SYNC) == 0))
|
||||
{
|
||||
mutecurrentslot = 1;
|
||||
if (m_dsdDecoder->m_state.currentslot == 0)
|
||||
{
|
||||
sprintf(m_dsdDecoder->m_state.slot0light, "[slot0]");
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(m_dsdDecoder->m_state.slot1light, "[slot1]");
|
||||
}
|
||||
}
|
||||
else if ((strcmp(sync, DMR_BS_VOICE_SYNC) == 0)
|
||||
|| (strcmp(sync, DMR_MS_VOICE_SYNC) == 0))
|
||||
{
|
||||
mutecurrentslot = 0;
|
||||
if (m_dsdDecoder->m_state.currentslot == 0)
|
||||
{
|
||||
sprintf(m_dsdDecoder->m_state.slot0light, "[SLOT0]");
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(m_dsdDecoder->m_state.slot1light, "[SLOT1]");
|
||||
}
|
||||
}
|
||||
if ((strcmp(sync, DMR_MS_VOICE_SYNC) == 0)
|
||||
|| (strcmp(sync, DMR_MS_DATA_SYNC) == 0))
|
||||
{
|
||||
msMode = 1;
|
||||
}
|
||||
|
||||
if ((m_majorBlock == 0) && (m_dsdDecoder->m_opts.errorbars == 1))
|
||||
{
|
||||
fprintf(stderr, "%s %s VOICE e:", m_dsdDecoder->m_state.slot0light, m_dsdDecoder->m_state.slot1light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSDDMRVoice::processSlot5(int symbolIndex) // Slot5 is a 18 symbol slot
|
||||
{
|
||||
int dibit = m_dsdDecoder->getDibit(); // get dibit from symbol and store it in cache
|
||||
m_dibitCache[m_dibitIndex] = dibit;
|
||||
|
||||
if (symbolIndex == 18-1) // last symbol -> launch process
|
||||
{
|
||||
int *dibitCache = &m_dibitCache[m_dibitIndex - symbolIndex]; // move back to start of corresponding cache section
|
||||
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
int dibit = dibitCache[i];
|
||||
|
||||
ambe_fr2[*w][*x] = (1 & (dibit >> 1)); // bit 1
|
||||
ambe_fr2[*y][*z] = (1 & dibit); // bit 0
|
||||
w++;
|
||||
x++;
|
||||
y++;
|
||||
z++;
|
||||
}
|
||||
|
||||
if (mutecurrentslot == 0)
|
||||
{
|
||||
if (m_dsdDecoder->m_state.firstframe == 1)
|
||||
{ // we don't know if anything received before the first sync after no carrier is valid
|
||||
m_dsdDecoder->m_state.firstframe = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_dsdDecoder->m_mbeDecoder.processFrame(0, ambe_fr, 0);
|
||||
m_dsdDecoder->m_mbeDecoder.processFrame(0, ambe_fr2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace dsdplus
|
||||
|
@ -42,7 +42,7 @@
|
||||
#ifndef DSDPLUS_DMR_VOICE_H_
|
||||
#define DSDPLUS_DMR_VOICE_H_
|
||||
|
||||
namespace DSDPlus
|
||||
namespace DSDplus
|
||||
{
|
||||
|
||||
class DSDDecoder;
|
||||
@ -57,12 +57,82 @@ public:
|
||||
void process();
|
||||
|
||||
private:
|
||||
int getSlotIndex(int symbolInMajorBlockIndex) //!< calculates current slot index and returns symbol index in the slot
|
||||
{
|
||||
if (symbolInMajorBlockIndex < 54)
|
||||
{
|
||||
m_slotIndex = 0;
|
||||
return symbolInMajorBlockIndex;
|
||||
}
|
||||
else if (symbolInMajorBlockIndex < 54+12)
|
||||
{
|
||||
m_slotIndex = 1;
|
||||
return symbolInMajorBlockIndex - 54;
|
||||
}
|
||||
else if (symbolInMajorBlockIndex < 54+12+36)
|
||||
{
|
||||
m_slotIndex = 2;
|
||||
return symbolInMajorBlockIndex - 54+12;
|
||||
}
|
||||
else if (symbolInMajorBlockIndex < 54+12+36+18)
|
||||
{
|
||||
m_slotIndex = 3;
|
||||
return symbolInMajorBlockIndex - 54+12+36;
|
||||
}
|
||||
else if (symbolInMajorBlockIndex < 54+12+36+18+24)
|
||||
{
|
||||
m_slotIndex = 4;
|
||||
return symbolInMajorBlockIndex - 54+12+36+18;
|
||||
}
|
||||
else if (symbolInMajorBlockIndex < 54+12+36+18+24+18)
|
||||
{
|
||||
m_slotIndex = 5;
|
||||
return symbolInMajorBlockIndex - 54+12+36+18+24;
|
||||
}
|
||||
else if (symbolInMajorBlockIndex < 54+12+36+18+24+18+36)
|
||||
{
|
||||
m_slotIndex = 6;
|
||||
return symbolInMajorBlockIndex - 54+12+36+18+24+18;
|
||||
}
|
||||
else if (symbolInMajorBlockIndex < 54+12+36+18+24+18+36+12)
|
||||
{
|
||||
m_slotIndex = 7;
|
||||
return symbolInMajorBlockIndex - 54+12+36+18+24+18+36;
|
||||
}
|
||||
else if (symbolInMajorBlockIndex < 54+12+36+18+24+18+36+12+54)
|
||||
{
|
||||
m_slotIndex = 8;
|
||||
return symbolInMajorBlockIndex - 54+12+36+18+24+18+36+12;
|
||||
}
|
||||
else if (symbolInMajorBlockIndex < 54+12+36+18+24+18+36+12+54+24)
|
||||
{
|
||||
m_slotIndex = 9;
|
||||
return symbolInMajorBlockIndex - 54+12+36+18+24+18+36+12+54;
|
||||
}
|
||||
else // cannot go there if using this function in its valid context (input is a remainder of division by 288)
|
||||
{
|
||||
m_slotIndex = -1; // invalid slot
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void preProcess(); //!< process the 144 in memory dibits in initial phase
|
||||
void processSlot0(int symbolIndex);
|
||||
void processSlot1(int symbolIndex);
|
||||
void processSlot2(int symbolIndex);
|
||||
void processSlot3(int symbolIndex);
|
||||
void processSlot4(int symbolIndex);
|
||||
void processSlot5(int symbolIndex);
|
||||
void processSlot6(int symbolIndex);
|
||||
void processSlot7(int symbolIndex);
|
||||
void processSlot8(int symbolIndex);
|
||||
void processSlot9(int symbolIndex);
|
||||
|
||||
DSDDecoder *m_dsdDecoder;
|
||||
// extracts AMBE frames from DMR frame
|
||||
int m_slotIndex; //!< Slot index in major block 0..9 //i;
|
||||
int m_majorBlock; //!< Major block index 0..5 //j;
|
||||
int dibit;
|
||||
int m_symbolIndex; //!< Current absolute symbol index
|
||||
int m_slotIndex; //!< Slot index in major block 0..9 //i;
|
||||
int m_majorBlock; //!< Major block index 0..5 //j;
|
||||
int *dibit_p;
|
||||
char ambe_fr[4][24];
|
||||
char ambe_fr2[4][24];
|
||||
@ -73,8 +143,14 @@ private:
|
||||
char cachdata[13];
|
||||
int mutecurrentslot;
|
||||
int msMode;
|
||||
int m_dibitCache[54]; // biggest slot is 54 dibits
|
||||
int m_dibitIndex; // index in dibit cache
|
||||
int m_dibitCache[288]; // has to handle a complete frame (288 dibits)
|
||||
int m_dibitIndex; // index in dibit cache
|
||||
|
||||
static const int rW[36];
|
||||
static const int rX[36];
|
||||
static const int rY[36];
|
||||
static const int rZ[36];
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -17,12 +17,14 @@
|
||||
#include <stdlib.h>
|
||||
#include "dsd_decoder.h"
|
||||
|
||||
namespace DSDPlus
|
||||
namespace DSDplus
|
||||
{
|
||||
|
||||
DSDDecoder::DSDDecoder() :
|
||||
m_symbol(0),
|
||||
m_fsmState(DSDLookForSync),
|
||||
m_hasSync(0),
|
||||
m_mbeDecoder(this),
|
||||
m_dsdDMRVoice(this)
|
||||
{
|
||||
resetSymbol();
|
||||
@ -36,27 +38,32 @@ DSDDecoder::~DSDDecoder()
|
||||
|
||||
void DSDDecoder::run(short sample)
|
||||
{
|
||||
if (pushSample(sample, 0))
|
||||
if (pushSample(sample, 0)) // a symbol is retrieved
|
||||
{
|
||||
switch (m_fsmState)
|
||||
{
|
||||
case DSDLookForSync:
|
||||
m_state.synctype = getFrameSync();
|
||||
m_hasSync = 0;
|
||||
m_state.synctype = getFrameSync(); // -> -2: still looking, -1 not found, 0 and above: sync found
|
||||
|
||||
if (m_state.synctype > -2)
|
||||
if (m_state.synctype > -2) // -1 and above means syncing has been processed (sync found or not but not searching)
|
||||
{
|
||||
// TODO: deal with the noCarrier() call
|
||||
// recalibrate center/umid/lmid
|
||||
m_state.center = ((m_state.max) + (m_state.min)) / 2;
|
||||
m_state.umid = (((m_state.max) - m_state.center) * 5 / 8) + m_state.center;
|
||||
m_state.lmid = (((m_state.min) - m_state.center) * 5 / 8) + m_state.center;
|
||||
|
||||
if (m_state.synctype > -1)
|
||||
if (m_state.synctype > -1) // 0 and above means a sync has been found
|
||||
{
|
||||
processFrame();
|
||||
m_hasSync = 1;
|
||||
processFrame(); // process the frame which sync has been found. This will change FSM state
|
||||
}
|
||||
else // no sync has been found after searching -> call noCarrier() and go back searching (same FSM state)
|
||||
{
|
||||
noCarrier();
|
||||
}
|
||||
}
|
||||
|
||||
// still searching -> no change in FSM state
|
||||
break;
|
||||
case DSDprocessDMRvoice:
|
||||
m_dsdDMRVoice.process();
|
||||
@ -111,7 +118,7 @@ bool DSDDecoder::pushSample(short sample, int have_sync)
|
||||
m_sampleIndex--;
|
||||
}
|
||||
else if ((m_state.jitter >= m_state.symbolCenter + 1)
|
||||
&& (m_state.jitter <= m_state.symbolCenter + 2))
|
||||
&& (m_state.jitter <= m_state.symbolCenter + 2))
|
||||
{
|
||||
m_sampleIndex++;
|
||||
}
|
||||
@ -124,7 +131,7 @@ bool DSDDecoder::pushSample(short sample, int have_sync)
|
||||
m_sampleIndex--; // catch up
|
||||
}
|
||||
else if ((m_state.jitter > m_state.symbolCenter)
|
||||
&& (m_state.jitter < m_state.samplesPerSymbol))
|
||||
&& (m_state.jitter < m_state.samplesPerSymbol))
|
||||
{
|
||||
m_sampleIndex++; // fall back
|
||||
}
|
||||
@ -140,8 +147,8 @@ bool DSDDecoder::pushSample(short sample, int have_sync)
|
||||
{
|
||||
sample = m_dsdFilters.dmr_filter(sample);
|
||||
}
|
||||
else if (m_state.lastsynctype == 8 || m_state.lastsynctype == 9
|
||||
|| m_state.lastsynctype == 16 || m_state.lastsynctype == 17)
|
||||
else if (m_state.lastsynctype == 8 || m_state.lastsynctype == 9
|
||||
|| m_state.lastsynctype == 16 || m_state.lastsynctype == 17)
|
||||
{
|
||||
sample = m_dsdFilters.nxdn_filter(sample);
|
||||
}
|
||||
@ -174,7 +181,7 @@ bool DSDDecoder::pushSample(short sample, int have_sync)
|
||||
m_state.jitter = m_sampleIndex;
|
||||
}
|
||||
if ((m_opts.symboltiming == 1) && (have_sync == 0)
|
||||
&& (m_state.lastsynctype != -1))
|
||||
&& (m_state.lastsynctype != -1))
|
||||
{
|
||||
fprintf(stderr, "O");
|
||||
}
|
||||
@ -182,13 +189,13 @@ bool DSDDecoder::pushSample(short sample, int have_sync)
|
||||
else
|
||||
{
|
||||
if ((m_opts.symboltiming == 1) && (have_sync == 0)
|
||||
&& (m_state.lastsynctype != -1))
|
||||
&& (m_state.lastsynctype != -1))
|
||||
{
|
||||
fprintf(stderr, "+");
|
||||
}
|
||||
if ((m_state.jitter < 0)
|
||||
&& (m_state.lastsample < m_state.center)
|
||||
&& (m_state.rf_mod != 1))
|
||||
&& (m_state.lastsample < m_state.center)
|
||||
&& (m_state.rf_mod != 1))
|
||||
{ // first transition edge
|
||||
m_state.jitter = m_sampleIndex;
|
||||
}
|
||||
@ -211,7 +218,7 @@ bool DSDDecoder::pushSample(short sample, int have_sync)
|
||||
m_state.jitter = m_sampleIndex;
|
||||
}
|
||||
if ((m_opts.symboltiming == 1) && (have_sync == 0)
|
||||
&& (m_state.lastsynctype != -1))
|
||||
&& (m_state.lastsynctype != -1))
|
||||
{
|
||||
fprintf(stderr, "X");
|
||||
}
|
||||
@ -219,13 +226,13 @@ bool DSDDecoder::pushSample(short sample, int have_sync)
|
||||
else
|
||||
{
|
||||
if ((m_opts.symboltiming == 1) && (have_sync == 0)
|
||||
&& (m_state.lastsynctype != -1))
|
||||
&& (m_state.lastsynctype != -1))
|
||||
{
|
||||
fprintf(stderr, "-");
|
||||
}
|
||||
if ((m_state.jitter < 0)
|
||||
&& (m_state.lastsample > m_state.center)
|
||||
&& (m_state.rf_mod != 1))
|
||||
&& (m_state.lastsample > m_state.center)
|
||||
&& (m_state.rf_mod != 1))
|
||||
{ // first transition edge
|
||||
m_state.jitter = m_sampleIndex;
|
||||
}
|
||||
@ -290,6 +297,292 @@ bool DSDDecoder::pushSample(short sample, int have_sync)
|
||||
}
|
||||
}
|
||||
|
||||
int DSDDecoder::getDibit()
|
||||
{
|
||||
// returns one dibit value
|
||||
int i, j, o, symbol;
|
||||
int sbuf2[128];
|
||||
int spectrum[64];
|
||||
char modulation[8];
|
||||
int lmin, lmax, lsum;
|
||||
|
||||
m_state.numflips = 0;
|
||||
|
||||
symbol = m_symbol;
|
||||
m_state.sbuf[m_state.sidx] = m_symbol;
|
||||
|
||||
for (i = 0; i < m_opts.ssize; i++)
|
||||
{
|
||||
sbuf2[i] = m_state.sbuf[i];
|
||||
}
|
||||
|
||||
qsort(sbuf2, m_opts.ssize, sizeof(int), comp);
|
||||
// continuous update of min/max in rf_mod=1 (QPSK) mode
|
||||
// in c4fm min/max must only be updated during sync
|
||||
if (m_state.rf_mod == 1)
|
||||
{
|
||||
lmin = (sbuf2[0] + sbuf2[1]) / 2;
|
||||
lmax = (sbuf2[(m_opts.ssize - 1)] + sbuf2[(m_opts.ssize - 2)]) / 2;
|
||||
m_state.minbuf[m_state.midx] = lmin;
|
||||
m_state.maxbuf[m_state.midx] = lmax;
|
||||
|
||||
if (m_state.midx == (m_opts.msize - 1))
|
||||
{
|
||||
m_state.midx = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state.midx++;
|
||||
}
|
||||
|
||||
lsum = 0;
|
||||
|
||||
for (i = 0; i < m_opts.msize; i++)
|
||||
{
|
||||
lsum += m_state.minbuf[i];
|
||||
}
|
||||
|
||||
m_state.min = lsum / m_opts.msize;
|
||||
lsum = 0;
|
||||
|
||||
for (i = 0; i < m_opts.msize; i++)
|
||||
{
|
||||
lsum += m_state.maxbuf[i];
|
||||
}
|
||||
|
||||
m_state.max = lsum / m_opts.msize;
|
||||
m_state.center = ((m_state.max) + (m_state.min)) / 2;
|
||||
m_state.umid = (((m_state.max) - m_state.center) * 5 / 8) + m_state.center;
|
||||
m_state.lmid = (((m_state.min) - m_state.center) * 5 / 8) + m_state.center;
|
||||
m_state.maxref = ((m_state.max) * 0.80);
|
||||
m_state.minref = ((m_state.min) * 0.80);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state.maxref = m_state.max;
|
||||
m_state.minref = m_state.min;
|
||||
}
|
||||
|
||||
if (m_state.sidx == (m_opts.ssize - 1))
|
||||
{
|
||||
m_state.sidx = 0;
|
||||
|
||||
if (m_opts.datascope == 1)
|
||||
{
|
||||
if (m_state.rf_mod == 0)
|
||||
{
|
||||
sprintf(modulation, "C4FM");
|
||||
}
|
||||
else if (m_state.rf_mod == 1)
|
||||
{
|
||||
sprintf(modulation, "QPSK");
|
||||
}
|
||||
else if (m_state.rf_mod == 2)
|
||||
{
|
||||
sprintf(modulation, "GFSK");
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
spectrum[i] = 0;
|
||||
}
|
||||
for (i = 0; i < m_opts.ssize; i++)
|
||||
{
|
||||
o = (sbuf2[i] + 32768) / 1024;
|
||||
spectrum[o]++;
|
||||
}
|
||||
if (m_state.symbolcnt > (4800 / m_opts.scoperate))
|
||||
{
|
||||
m_state.symbolcnt = 0;
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr,
|
||||
"Demod mode: %s Nac: %4X\n",
|
||||
modulation, m_state.nac);
|
||||
fprintf(stderr,
|
||||
"Frame Type: %s Talkgroup: %7i\n",
|
||||
m_state.ftype, m_state.lasttg);
|
||||
fprintf(stderr,
|
||||
"Frame Subtype: %s Source: %12i\n",
|
||||
m_state.fsubtype, m_state.lastsrc);
|
||||
fprintf(stderr,
|
||||
"TDMA activity: %s %s Voice errors: %s\n",
|
||||
m_state.slot0light, m_state.slot1light, m_state.err_str);
|
||||
fprintf(stderr,
|
||||
"+----------------------------------------------------------------+\n");
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
fprintf(stderr, "|");
|
||||
|
||||
for (j = 0; j < 64; j++)
|
||||
{
|
||||
if (i == 0)
|
||||
{
|
||||
if ((j == ((m_state.min) + 32768) / 1024)
|
||||
|| (j == ((m_state.max) + 32768) / 1024))
|
||||
{
|
||||
fprintf(stderr, "#");
|
||||
}
|
||||
else if ((j == ((m_state.lmid) + 32768) / 1024)
|
||||
|| (j == ((m_state.umid) + 32768) / 1024))
|
||||
{
|
||||
fprintf(stderr, "^");
|
||||
}
|
||||
else if (j == (m_state.center + 32768) / 1024)
|
||||
{
|
||||
fprintf(stderr, "!");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (j == 32)
|
||||
{
|
||||
fprintf(stderr, "|");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spectrum[j] > 9 - i)
|
||||
{
|
||||
fprintf(stderr, "*");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (j == 32)
|
||||
{
|
||||
fprintf(stderr, "|");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "|\n");
|
||||
}
|
||||
fprintf(stderr,
|
||||
"+----------------------------------------------------------------+\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state.sidx++;
|
||||
}
|
||||
|
||||
if (m_state.dibit_buf_p > m_state.dibit_buf + 900000)
|
||||
{
|
||||
m_state.dibit_buf_p = m_state.dibit_buf + 200;
|
||||
}
|
||||
|
||||
// determine dibit state
|
||||
if ((m_state.synctype == 6) || (m_state.synctype == 14)
|
||||
|| (m_state.synctype == 18))
|
||||
{
|
||||
if (m_symbol > m_state.center)
|
||||
{
|
||||
*m_state.dibit_buf_p = 1;
|
||||
m_state.dibit_buf_p++;
|
||||
return (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_state.dibit_buf_p = 3;
|
||||
m_state.dibit_buf_p++;
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
else if ((m_state.synctype == 7) || (m_state.synctype == 15)
|
||||
|| (m_state.synctype == 19))
|
||||
{
|
||||
if (m_symbol > m_state.center)
|
||||
{
|
||||
*m_state.dibit_buf_p = 1;
|
||||
m_state.dibit_buf_p++;
|
||||
return (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_state.dibit_buf_p = 3;
|
||||
m_state.dibit_buf_p++;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
else if ((m_state.synctype == 1) || (m_state.synctype == 3)
|
||||
|| (m_state.synctype == 5) || (m_state.synctype == 9)
|
||||
|| (m_state.synctype == 11) || (m_state.synctype == 13))
|
||||
{
|
||||
if (m_symbol > m_state.center)
|
||||
{
|
||||
if (m_symbol > m_state.umid)
|
||||
{
|
||||
*m_state.dibit_buf_p = 1; // store non-inverted values in dibit_buf
|
||||
m_state.dibit_buf_p++;
|
||||
return (3);
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_state.dibit_buf_p = 0;
|
||||
m_state.dibit_buf_p++;
|
||||
return (2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_symbol < m_state.lmid)
|
||||
{
|
||||
*m_state.dibit_buf_p = 3;
|
||||
m_state.dibit_buf_p++;
|
||||
return (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_state.dibit_buf_p = 2;
|
||||
m_state.dibit_buf_p++;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_symbol > m_state.center)
|
||||
{
|
||||
if (m_symbol > m_state.umid)
|
||||
{
|
||||
*m_state.dibit_buf_p = 1;
|
||||
m_state.dibit_buf_p++;
|
||||
return (1);
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_state.dibit_buf_p = 0;
|
||||
m_state.dibit_buf_p++;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_symbol < m_state.lmid)
|
||||
{
|
||||
*m_state.dibit_buf_p = 3;
|
||||
m_state.dibit_buf_p++;
|
||||
return (3);
|
||||
}
|
||||
else
|
||||
{
|
||||
*m_state.dibit_buf_p = 2;
|
||||
m_state.dibit_buf_p++;
|
||||
return (2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSDDecoder::resetFrameSync()
|
||||
{
|
||||
for (int i = 18; i < 24; i++)
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "dsd_opts.h"
|
||||
#include "dsd_state.h"
|
||||
#include "dsd_filters.h"
|
||||
#include "dsd_mbe.h"
|
||||
#include "dmr_voice.h"
|
||||
|
||||
/*
|
||||
@ -57,7 +58,7 @@
|
||||
#define INV_PROVOICE_EA_SYNC "13313133113113333311313133133311"
|
||||
#define PROVOICE_EA_SYNC "31131311331331111133131311311133"
|
||||
|
||||
namespace DSDPlus
|
||||
namespace DSDplus
|
||||
{
|
||||
|
||||
class DSDDecoder
|
||||
@ -88,6 +89,7 @@ public:
|
||||
|
||||
private:
|
||||
bool pushSample(short sample, int have_sync); //!< push a new sample into the decoder. Returns true if a new symbol is available
|
||||
int getDibit(); //!< get dibit from the last retrieved symbol. Returns the dibit as its dibit value: 0,1,2,3
|
||||
int getFrameSync();
|
||||
void resetSymbol();
|
||||
void resetFrameSync();
|
||||
@ -119,8 +121,11 @@ private:
|
||||
int m_lsum;
|
||||
char m_spectrum[64];
|
||||
int m_t;
|
||||
int m_hasSync; //!< tells whether we are in synced phase
|
||||
// Other
|
||||
DSDFilters m_dsdFilters;
|
||||
// MBE decoder
|
||||
DSDMBEDecoder m_mbeDecoder;
|
||||
// Frame decoders
|
||||
DSDDMRVoice m_dsdDMRVoice;
|
||||
};
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "dsd_filters.h"
|
||||
|
||||
namespace DSDPlus
|
||||
namespace DSDplus
|
||||
{
|
||||
|
||||
// DMR filter
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define NXZEROS 134
|
||||
|
||||
|
||||
namespace DSDPlus
|
||||
namespace DSDplus
|
||||
{
|
||||
|
||||
class DSDFilters
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "dsd_opts.h"
|
||||
|
||||
namespace DSDPlus
|
||||
namespace DSDplus
|
||||
{
|
||||
|
||||
DSDOpts::DSDOpts()
|
||||
|
@ -17,7 +17,7 @@
|
||||
#ifndef DSDPLUS_DSD_OPTS_H_
|
||||
#define DSDPLUS_DSD_OPTS_H_
|
||||
|
||||
namespace DSDPlus
|
||||
namespace DSDplus
|
||||
{
|
||||
|
||||
class DSDOpts
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include "dsd_state.h"
|
||||
|
||||
namespace DSDPlus
|
||||
namespace DSDplus
|
||||
{
|
||||
|
||||
DSDState::DSDState()
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <string.h>
|
||||
#include <mbelib.h>
|
||||
|
||||
namespace DSDPlus
|
||||
namespace DSDplus
|
||||
{
|
||||
|
||||
class DSDState
|
||||
|
Loading…
Reference in New Issue
Block a user