Skip to content

Commit 4d5f7c9

Browse files
committed
properly zero bit buffer used for sample sync correlation; enhance debug logging to display the sample sync data; fix missed 1st LDU superframe after a HDU, this required adding a flag to indicate that the sync positions on the next frame cycle were LDU sync positions; refactor LDU frame writing into a separate helper function; fix issue where 1st LDU1 after a HDU would be ignored for processing (this simply required processing the LDU1 in processSamples() immediately instead of waiting for processVoice());
1 parent 0a4c784 commit 4d5f7c9

File tree

2 files changed

+96
-46
lines changed

2 files changed

+96
-46
lines changed

p25/P25RX.cpp

Lines changed: 89 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
66
*
77
* Copyright (C) 2009-2017 Jonathan Naylor, G4KLX
8-
* Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL
8+
* Copyright (C) 2017-2025 Bryan Biedenkapp, N2PLL
99
* Copyright (C) 2024 Patrick McDonnell, W3AXL
1010
*
1111
*/
@@ -60,11 +60,12 @@ P25RX::P25RX() :
6060
m_nac(0xF7EU),
6161
m_corrCountdown(CORRELATION_COUNTDOWN),
6262
m_state(P25RXS_NONE),
63+
m_lduSyncPos(false),
6364
m_duid(0xFFU),
6465
m_rssiAccum(0U),
6566
m_rssiCount(0U)
6667
{
67-
/* stub */
68+
m_bitBuffer[0U] = m_bitBuffer[1U] = m_bitBuffer[2U] = m_bitBuffer[3U] = m_bitBuffer[4U] = 0U;
6869
}
6970

7071
/* Helper to reset data values to defaults. */
@@ -79,6 +80,9 @@ void P25RX::reset()
7980
m_pduEndPtr = NOENDPTR;
8081
m_syncPtr = 0U;
8182

83+
m_bitPtr = 0U;
84+
m_bitBuffer[0U] = m_bitBuffer[1U] = m_bitBuffer[2U] = m_bitBuffer[3U] = m_bitBuffer[4U] = 0U;
85+
8286
m_maxCorr = 0;
8387
m_centreVal = 0;
8488
m_thresholdVal = 0;
@@ -89,6 +93,7 @@ void P25RX::reset()
8993

9094
DEBUG1("P25RX::samples() m_state = P25RXS_NONE");
9195
m_state = P25RXS_NONE;
96+
m_lduSyncPos = false;
9297

9398
m_duid = 0xFFU;
9499

@@ -143,20 +148,34 @@ void P25RX::samples(const q15_t* samples, uint16_t* rssi, uint8_t length)
143148
m_countdown--;
144149

145150
if (m_countdown == 1U) {
146-
m_minSyncPtr = m_syncPtr + P25_HDU_FRAME_LENGTH_SAMPLES - 1U;
147-
if (m_minSyncPtr >= P25_LDU_FRAME_LENGTH_SAMPLES)
148-
m_minSyncPtr -= P25_LDU_FRAME_LENGTH_SAMPLES;
149-
150-
m_maxSyncPtr = m_syncPtr + P25_HDU_FRAME_LENGTH_SAMPLES + 1U;
151-
if (m_maxSyncPtr >= P25_LDU_FRAME_LENGTH_SAMPLES)
152-
m_maxSyncPtr -= P25_LDU_FRAME_LENGTH_SAMPLES;
151+
// are we using LDU sync positions?
152+
if (m_lduSyncPos) {
153+
m_minSyncPtr = m_syncPtr + P25_LDU_FRAME_LENGTH_SAMPLES - 1U;
154+
if (m_minSyncPtr >= P25_LDU_FRAME_LENGTH_SAMPLES)
155+
m_minSyncPtr -= P25_LDU_FRAME_LENGTH_SAMPLES;
156+
157+
m_maxSyncPtr = m_syncPtr + 1U;
158+
if (m_maxSyncPtr >= P25_LDU_FRAME_LENGTH_SAMPLES)
159+
m_maxSyncPtr -= P25_LDU_FRAME_LENGTH_SAMPLES;
160+
161+
m_lostCount = MAX_SYNC_FRAMES;
162+
} else {
163+
m_minSyncPtr = m_syncPtr + P25_HDU_FRAME_LENGTH_SAMPLES - 1U;
164+
if (m_minSyncPtr >= P25_LDU_FRAME_LENGTH_SAMPLES)
165+
m_minSyncPtr -= P25_LDU_FRAME_LENGTH_SAMPLES;
166+
167+
m_maxSyncPtr = m_syncPtr + P25_HDU_FRAME_LENGTH_SAMPLES + 1U;
168+
if (m_maxSyncPtr >= P25_LDU_FRAME_LENGTH_SAMPLES)
169+
m_maxSyncPtr -= P25_LDU_FRAME_LENGTH_SAMPLES;
170+
}
153171

154172
DEBUG4("P25RX::samples() dataPtr/startPtr/endPtr", m_dataPtr, m_startPtr, m_endPtr);
155173
DEBUG4("P25RX::samples() lostCount/maxSyncPtr/minSyncPtr", m_lostCount, m_maxSyncPtr, m_minSyncPtr);
156174

175+
m_countdown = 0U;
176+
157177
DEBUG1("P25RX::samples() m_state = P25RXS_SYNC");
158178
m_state = P25RXS_SYNC;
159-
m_countdown = 0U;
160179
}
161180
}
162181

@@ -229,7 +248,10 @@ void P25RX::processSample(q15_t sample)
229248

230249
frame[0U] = 0x01U; // has sync
231250
serial.writeP25Data(frame, P25_HDU_FRAME_LENGTH_BYTES + 1U);
232-
//reset();
251+
reset();
252+
253+
// setup next cycle to use LDU sync positions
254+
m_lduSyncPos = true;
233255
}
234256
return;
235257
case P25_DUID_TDU:
@@ -248,8 +270,15 @@ void P25RX::processSample(q15_t sample)
248270
return;
249271
case P25_DUID_LDU1:
250272
case P25_DUID_VSELP1:
251-
DEBUG1("P25RX::samples() m_state = P25RXS_VOICE");
252-
m_state = P25RXS_VOICE;
273+
{
274+
// are we using LDU sync positions?
275+
if (m_lduSyncPos) {
276+
writeLDUFrame();
277+
}
278+
279+
DEBUG1("P25RX::samples() m_state = P25RXS_VOICE (LDU1)");
280+
m_state = P25RXS_VOICE;
281+
}
253282
break;
254283
case P25_DUID_TSDU:
255284
{
@@ -267,7 +296,7 @@ void P25RX::processSample(q15_t sample)
267296
return;
268297
case P25_DUID_LDU2:
269298
case P25_DUID_VSELP2:
270-
DEBUG1("P25RX::samples() m_state = P25RXS_VOICE");
299+
DEBUG1("P25RX::samples() m_state = P25RXS_VOICE (LDU2)");
271300
m_state = P25RXS_VOICE;
272301
break;
273302
case P25_DUID_PDU:
@@ -297,17 +326,20 @@ void P25RX::processSample(q15_t sample)
297326
}
298327
}
299328

300-
m_minSyncPtr = m_syncPtr + P25_LDU_FRAME_LENGTH_SAMPLES - 1U;
301-
if (m_minSyncPtr >= P25_LDU_FRAME_LENGTH_SAMPLES)
302-
m_minSyncPtr -= P25_LDU_FRAME_LENGTH_SAMPLES;
329+
// late entry?
330+
if (!m_lduSyncPos) {
331+
m_minSyncPtr = m_syncPtr + P25_LDU_FRAME_LENGTH_SAMPLES - 1U;
332+
if (m_minSyncPtr >= P25_LDU_FRAME_LENGTH_SAMPLES)
333+
m_minSyncPtr -= P25_LDU_FRAME_LENGTH_SAMPLES;
303334

304-
m_maxSyncPtr = m_syncPtr + 1U;
305-
if (m_maxSyncPtr >= P25_LDU_FRAME_LENGTH_SAMPLES)
306-
m_maxSyncPtr -= P25_LDU_FRAME_LENGTH_SAMPLES;
335+
m_maxSyncPtr = m_syncPtr + 1U;
336+
if (m_maxSyncPtr >= P25_LDU_FRAME_LENGTH_SAMPLES)
337+
m_maxSyncPtr -= P25_LDU_FRAME_LENGTH_SAMPLES;
307338

308-
m_maxCorr = 0;
339+
m_maxCorr = 0;
309340

310-
m_lostCount = MAX_SYNC_FRAMES;
341+
m_lostCount = MAX_SYNC_FRAMES;
342+
}
311343

312344
m_rssiAccum = 0U;
313345
m_rssiCount = 0U;
@@ -389,28 +421,8 @@ void P25RX::processVoice(q15_t sample)
389421
return;
390422
}
391423

392-
calculateLevels(m_startPtr, P25_LDU_FRAME_LENGTH_SYMBOLS);
393-
394-
DEBUG4("P25RX::processVoice() sync found in LDU pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
424+
writeLDUFrame();
395425

396-
uint8_t frame[P25_LDU_FRAME_LENGTH_BYTES + 3U];
397-
samplesToBits(m_startPtr, P25_LDU_FRAME_LENGTH_SYMBOLS, frame, P25_NID_LENGTH_SYMBOLS, m_centreVal, m_thresholdVal);
398-
399-
frame[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; // set sync flag
400-
#if defined(SEND_RSSI_DATA)
401-
if (m_rssiCount > 0U) {
402-
uint16_t rssi = m_rssiAccum / m_rssiCount;
403-
frame[217U] = (rssi >> 8) & 0xFFU;
404-
frame[218U] = (rssi >> 0) & 0xFFU;
405-
406-
serial.writeP25Data(false, frame, P25_LDU_FRAME_LENGTH_BYTES + 3U);
407-
}
408-
else {
409-
serial.writeP25Data(false, frame, P25_LDU_FRAME_LENGTH_BYTES + 1U);
410-
}
411-
#else
412-
serial.writeP25Data(frame, P25_LDU_FRAME_LENGTH_BYTES + 1U);
413-
#endif
414426
m_rssiAccum = 0U;
415427
m_rssiCount = 0U;
416428

@@ -420,6 +432,34 @@ void P25RX::processVoice(q15_t sample)
420432
}
421433
}
422434

435+
/* Helper to write a LDU data frame. */
436+
437+
void P25RX::writeLDUFrame()
438+
{
439+
calculateLevels(m_startPtr, P25_LDU_FRAME_LENGTH_SYMBOLS);
440+
441+
DEBUG4("P25RX::writeLDUFrame() sync found in LDUx pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
442+
443+
uint8_t frame[P25_LDU_FRAME_LENGTH_BYTES + 3U];
444+
samplesToBits(m_startPtr, P25_LDU_FRAME_LENGTH_SYMBOLS, frame, P25_NID_LENGTH_SYMBOLS, m_centreVal, m_thresholdVal);
445+
446+
frame[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; // set sync flag
447+
#if defined(SEND_RSSI_DATA)
448+
if (m_rssiCount > 0U) {
449+
uint16_t rssi = m_rssiAccum / m_rssiCount;
450+
frame[217U] = (rssi >> 8) & 0xFFU;
451+
frame[218U] = (rssi >> 0) & 0xFFU;
452+
453+
serial.writeP25Data(false, frame, P25_LDU_FRAME_LENGTH_BYTES + 3U);
454+
}
455+
else {
456+
serial.writeP25Data(false, frame, P25_LDU_FRAME_LENGTH_BYTES + 1U);
457+
}
458+
#else
459+
serial.writeP25Data(frame, P25_LDU_FRAME_LENGTH_BYTES + 1U);
460+
#endif
461+
}
462+
423463
/* Helper to process PDU P25 samples. */
424464

425465
void P25RX::processData(q15_t sample)
@@ -493,9 +533,9 @@ void P25RX::processData(q15_t sample)
493533

494534
bool P25RX::correlateSync()
495535
{
496-
uint8_t errs = countBits32((m_bitBuffer[m_bitPtr] & P25_SYNC_SYMBOLS_MASK) ^ P25_SYNC_SYMBOLS);
536+
uint8_t symErrs = countBits32((m_bitBuffer[m_bitPtr] & P25_SYNC_SYMBOLS_MASK) ^ P25_SYNC_SYMBOLS);
497537

498-
if (errs <= MAX_SYNC_SYMBOLS_ERRS) {
538+
if (symErrs <= MAX_SYNC_SYMBOLS_ERRS) {
499539
uint16_t ptr = m_dataPtr + P25_LDU_FRAME_LENGTH_SAMPLES - P25_SYNC_LENGTH_SAMPLES + P25_RADIO_SYMBOL_LENGTH;
500540
if (ptr >= P25_LDU_FRAME_LENGTH_SAMPLES)
501541
ptr -= P25_LDU_FRAME_LENGTH_SAMPLES;
@@ -558,6 +598,10 @@ bool P25RX::correlateSync()
558598
errs += countBits8(sync[i] ^ P25_SYNC_BYTES[i]);
559599

560600
if (errs <= maxErrs) {
601+
DEBUG2("P25RX::correlateSync() symbol errs", symErrs);
602+
DEBUG2("P25RX::correlateSync() bitPtr", m_bitPtr);
603+
DEBUG5("P25RX::correlateSync() bitBuffer", (m_bitBuffer[m_bitPtr] >> 24) & 0xFFU, (m_bitBuffer[m_bitPtr] >> 16) & 0xFFU, (m_bitBuffer[m_bitPtr] >> 8) & 0xFFU, m_bitBuffer[m_bitPtr] & 0xFFU);
604+
561605
DEBUG2("P25RX::correlateSync() sync errs", errs);
562606

563607
DEBUG4("P25RX::correlateSync() sync [b0 - b2]", sync[0], sync[1], sync[2]);

p25/P25RX.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
66
*
77
* Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX
8-
* Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL
8+
* Copyright (C) 2017-2025 Bryan Biedenkapp, N2PLL
99
*
1010
*/
1111
/**
@@ -106,6 +106,7 @@ namespace p25
106106
uint8_t m_corrCountdown;
107107

108108
P25RX_STATE m_state;
109+
bool m_lduSyncPos;
109110

110111
uint8_t m_duid;
111112

@@ -128,6 +129,11 @@ namespace p25
128129
*/
129130
void processData(q15_t sample);
130131

132+
/**
133+
* @brief Helper to write a LDU data frame.
134+
*/
135+
void writeLDUFrame();
136+
131137
/**
132138
* @brief Frame synchronization correlator.
133139
* @returns bool

0 commit comments

Comments
 (0)