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
425465void P25RX::processData (q15_t sample)
@@ -493,9 +533,9 @@ void P25RX::processData(q15_t sample)
493533
494534bool 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 ]);
0 commit comments