Compare commits

..
Author SHA1 Message Date
Jonathan Naylor 459a1413b7 Merge branch 'FM' into dstar_correlator_fm 2020-05-21 10:58:44 +01:00
Jonathan Naylor 2cf2ce4dfa Fix the TX Hang handling. 2020-05-20 15:16:12 +01:00
Jonathan Naylor 5f29808b80 Set the COS LED correctly. 2020-05-19 12:09:44 +01:00
Jonathan Naylor 063b21f999 Try and make the closing callsign appear. 2020-05-18 11:09:56 +01:00
Jonathan Naylor 89b8641955 Merge pull request #278 from shawnchain/drcc_serial_bugfix
Drcc serial bugfix
2020-05-18 06:34:09 +01:00
Shawn Chain 6397c720e8 Generate bin map file for analysis 2020-05-18 12:19:22 +08:00
Shawn Chain 50c1e5aa3f update pin defs for drcc/nqf board 2020-05-18 12:18:44 +08:00
Shawn Chain 970d02773f Fix serial no write bug on DRCC board 2020-05-18 12:18:17 +08:00
Jonathan Naylor ff9fb61467 Merge branch 'FM' into dstar_correlator_fm 2020-05-14 13:41:32 +01:00
Jonathan Naylor ff375abb0e Hold off the mode change until the ack and callsign have been
transmitted.
2020-05-14 12:10:37 +01:00
Jonathan Naylor 63e456919a Merge branch 'FM' into dstar_correlator_fm 2020-05-13 12:04:06 +01:00
Jonathan Naylor 7169836621 Merge branch 'master' into FM 2020-05-13 12:01:19 +01:00
Jonathan Naylor 48034189d2 Merge branch 'FM' into dstar_correlator_fm 2020-05-13 10:32:10 +01:00
Jonathan Naylor 8e52bdcc5c Merge branch 'master' into FM 2020-05-13 10:30:46 +01:00
Jonathan Naylor 66feb9d50b Merge branch 'master' into FM 2020-05-12 15:48:44 +01:00
Jonathan Naylor 60d654865d Merge branch 'FM' into dstar_correlator_fm 2020-05-12 15:20:36 +01:00
Jonathan Naylor 435544f7a1 Add CTCSS hysteresis. 2020-05-12 13:55:30 +01:00
Jonathan Naylor 75e32e1b71 Merge branch 'master' into FM 2020-05-11 13:41:37 +01:00
Jonathan Naylor c54c13c146 Merge branch 'master' into FM 2020-05-11 13:33:49 +01:00
Jonathan Naylor 4cba5931f4 Loosen the conditions for returning to STATE_IDLE 2020-05-10 21:29:01 +01:00
Jonathan Naylor d0062a55f8 Rescale the FM calibration output. 2020-05-10 17:31:21 +01:00
Jonathan Naylor 66ea3ad0d1 Only use the CTCSS delay when not using COS. 2020-05-10 17:15:54 +01:00
Jonathan Naylor 85acdc7121 Merge pull request #259 from F4FXL/FM
Fix stuck on TX
2020-05-10 17:06:26 +01:00
Geoffrey Merck a2518e99f2 Fix stuck on TX 2020-05-10 17:29:17 +02:00
Jonathan Naylor 3bb7cde322 Add input audio delay to match the CTCSS decoder results. 2020-05-09 13:01:02 +01:00
Jonathan Naylor fa29a27695 Ensure all output audio is flushed before leaving FM state. 2020-05-09 12:53:50 +01:00
Jonathan Naylor e30eb3adaf Reduce the output buffer loading. 2020-05-08 17:18:26 +01:00
Jonathan Naylor 9b0fed975c Buffer output after adding some initial silence. 2020-05-08 15:48:03 +01:00
Jonathan Naylor 5ca9313db8 Merge pull request #248 from F4FXL/FM
Make the FM chain RX Level independant
2020-05-08 09:18:58 +01:00
Geoffrey Merck feff1ee2c7 remove emphasis 2020-05-08 09:04:28 +02:00
Geoffrey Merck 77e0deee76 Make whole FM chain RX level independant 2020-05-08 09:01:00 +02:00
Jonathan Naylor 6769a6a0d7 Merge branch 'FM' into dstar_correlator_fm 2020-05-06 11:35:06 +01:00
Jonathan Naylor c6485de10c Merge branch 'FM' into dstar_correlator_fm 2020-05-05 21:04:08 +01:00
Jonathan Naylor cc018515e1 Merge branch 'FM' into dstar_correlator_fm 2020-05-02 17:53:24 +01:00
Jonathan Naylor 278622dd88 Merge branch 'FM' into dstar_correlator_fm 2020-05-02 16:52:27 +01:00
Jonathan Naylor 783822e401 Merge branch 'FM' into dstar_correlator_fm 2020-05-01 18:48:04 +01:00
Jonathan Naylor 45cdd8f799 Merge branch 'FM' into dstar_correlator_fm 2020-04-29 21:52:04 +01:00
Jonathan Naylor 85e33bc49f Merge branch 'FM' into dstar_correlator_fm 2020-04-29 21:39:09 +01:00
Jonathan Naylor 917dab755a Merge branch 'master' into dstar_correlator 2020-04-29 21:29:46 +01:00
Jonathan Naylor 1d75a360ea Merge branch 'master' into dstar_correlator 2019-07-15 09:11:10 +01:00
Jonathan Naylor 4593951680 Merge branch 'master' into dstar_correlator 2019-05-19 13:26:03 +01:00
Jonathan Naylor 10a043f641 Merge branch 'master' into dstar_correlator 2019-01-31 08:10:07 +00:00
Jonathan Naylor 2f05727b25 Merge branch 'master' into dstar_correlator 2018-10-31 14:51:20 +00:00
Jonathan Naylor 7519429c43 Merge branch 'master' into dstar_correlator 2018-10-14 17:26:24 +01:00
Jonathan Naylor b0e2867663 Merge branch 'master' into dstar_correlator 2018-09-18 09:29:04 +01:00
Jonathan Naylor cb25a64a4b Merge branch 'master' into dstar_correlator 2018-09-02 13:14:02 +01:00
Jonathan Naylor 2099096acb Merge branch 'master' into dstar_correlator 2018-07-24 19:14:47 +01:00
Jonathan Naylor 51b0be7e2e Merge branch 'master' into dstar_correlator 2018-07-23 21:54:37 +01:00
Jonathan Naylor d30d768bdc Merge branch 'master' into dstar_correlator 2018-07-23 17:48:55 +01:00
Jonathan Naylor 7107625b12 Merge branch 'master' into dstar_correlator 2018-07-19 18:22:18 +01:00
Jonathan Naylor 554094540d Merge branch 'master' into dstar_correlator 2018-07-13 08:10:52 +01:00
Jonathan Naylor ddaac983a4 Merge branch 'master' into dstar_correlator 2018-07-05 18:45:17 +01:00
Jonathan Naylor 4b3736a189 Merge branch 'master' into dstar_correlator 2018-07-05 18:32:27 +01:00
Jonathan Naylor fd5822df19 Merge branch 'master' into dstar_correlator 2018-06-04 20:51:51 +01:00
Jonathan Naylor 508c3000fa Merge branch 'master' into dstar_correlator 2018-05-15 18:33:22 +01:00
Jonathan Naylor fcd1012ff4 Merge branch 'master' into dstar_correlator 2018-05-14 18:46:11 +01:00
Jonathan Naylor f2e9f2d753 Merge branch 'master' into dstar_correlator 2018-04-30 18:00:13 +01:00
Jonathan Naylor 96dc2282a8 Merge branch 'master' into dstar_correlator 2018-04-17 22:33:28 +01:00
Jonathan Naylor 00891dfa2f Merge branch 'master' into dstar_correlator 2018-03-27 21:36:52 +01:00
Jonathan Naylor 0bfc59b2d7 Merge branch 'master' into dstar_correlator 2018-03-22 07:10:50 +00:00
Jonathan Naylor 387221665f Merge branch 'master' into dstar_correlator 2018-03-07 20:05:13 +00:00
Jonathan Naylor 8da0ea7740 Merge branch 'master' into dstar_correlator 2018-02-26 19:55:53 +00:00
Jonathan Naylor 46035fa212 Merge branch 'master' into dstar_correlator 2018-01-11 07:28:15 +00:00
Jonathan Naylor aa52b03bc2 Merge branch 'master' into dstar_correlator 2018-01-08 18:23:55 +00:00
Jonathan Naylor cf849ccf65 Merge branch 'master' into dstar_correlator 2018-01-01 13:36:03 +00:00
Jonathan Naylor 83dd360062 Merge pull request #128 from F4FXL/dstar_correlator
Fixes erroneous end sync seen on station having QSB
2017-12-16 21:03:53 +00:00
F4FXL 551aa3bb20 Fixes erroneous end of frame seen on station having QSB 2017-12-16 09:02:15 +01:00
Jonathan Naylor cb78220156 Merge branch 'master' into dstar_correlator 2017-11-06 09:33:44 +00:00
Jonathan Naylor 22297c613c Merge branch 'master' into dstar_correlator 2017-10-30 14:06:42 +00:00
Jonathan Naylor 24741a11c6 Merge branch 'master' into dstar_correlator 2017-10-28 12:45:40 +01:00
Jonathan Naylor 293a5b6912 Merge branch 'master' into dstar_correlator 2017-10-15 13:21:50 +01:00
Jonathan Naylor 7e8d018242 Merge branch 'master' into dstar_correlator 2017-10-02 16:35:30 +01:00
Jonathan Naylor 3b84cf85c3 Merge branch 'master' into dstar_correlator 2017-09-27 09:21:56 +01:00
Jonathan Naylor ef8f5bb80b Merge branch 'master' into dstar_correlator 2017-09-10 14:40:40 +01:00
Jonathan Naylor 037810b23b Merge branch 'master' into dstar_correlator 2017-09-07 09:03:34 +01:00
Jonathan Naylor f7de632cd5 Merge branch 'master' into dstar_correlator 2017-08-31 08:39:36 +01:00
Jonathan Naylor a554a86202 Merge branch 'master' into dstar_correlator 2017-08-30 09:18:11 +01:00
Jonathan Naylor 4eda2b61f5 Merge pull request #109 from juribeparada/dstar_correlator
Adding support for STM32F767 dstar_correlator branch
2017-08-29 09:17:09 +01:00
Jonathan Naylor f06bd5125b Merge branch 'dstar_correlator' into dstar_correlator 2017-08-29 09:17:01 +01:00
Jonathan Naylor a0afe0e54f Merge branch 'master' into dstar_correlator 2017-08-29 08:50:44 +01:00
Andy CA6JAU edbf2b3ec0 Fix typo 2017-08-28 23:02:28 -03:00
Andy CA6JAU 2833ed2d2e Adding support for STM32F767 dstar_correlator branch 2017-08-28 22:42:26 -03:00
Jonathan Naylor d91a155084 Add watchdog to host serial port. 2017-08-20 15:59:48 +01:00
Jonathan Naylor dc9d83f9f0 Add optional TX DC offset. 2017-08-20 12:19:04 +01:00
Jonathan Naylor 2a5690fd4d Re-add the const qualifiers. 2017-08-18 11:02:33 +01:00
Jonathan Naylor 161736925e Optimise the DC offset processing. 2017-08-18 10:55:32 +01:00
Jonathan Naylor c43616f3c5 Enhancements suggested by IZ1MLT. 2017-08-13 18:40:05 +01:00
Jonathan Naylor e6adc0a296 Forgot the Q31 to Q15 conversion. 2017-08-02 20:38:46 +01:00
Jonathan Naylor f195fd6f66 Merge branch 'master' into dstar_correlator 2017-08-02 19:39:15 +01:00
Jonathan Naylor 16a43db79a Further optimisation of the calculated values. 2017-07-17 21:26:39 +01:00
Jonathan Naylor a033b2db7b Adjust values slightly. 2017-07-17 21:16:24 +01:00
Jonathan Naylor 88ab312da0 Merge branch 'master' into dstar_correlator 2017-07-16 19:22:56 +01:00
Jonathan Naylor 49383ca921 Get the RSSI working properly and simplify calculations. 2017-07-16 18:46:09 +01:00
Jonathan Naylor ed07175437 Tweak the settings. 2017-07-11 21:10:03 +01:00
Jonathan Naylor c8208ab1df Added extra debugging and updated position calculations. 2017-07-10 19:58:50 +01:00
Jonathan Naylor 90797696dd First compileable version, but untested. 2017-07-06 20:28:20 +01:00
Jonathan Naylor c22f360ed1 More changes to the D-Star RX. 2017-07-03 20:26:24 +01:00
Jonathan Naylor 5d74c2f7bf First changes for correlation of D-Star. 2017-07-02 17:57:17 +01:00
23 changed files with 650 additions and 290 deletions
+1 -1
View File
@@ -24,7 +24,7 @@
const unsigned int BUFFER_LENGTH = 200U; const unsigned int BUFFER_LENGTH = 200U;
const uint32_t PLLMAX = 0x10000U; const uint32_t PLLMAX = 0x10000U;
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH; const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_SYMBOL_LENGTH;
const uint32_t INC = PLLINC / 32U; const uint32_t INC = PLLINC / 32U;
// D-Star bit order version of 0x55 0x2D 0x16 // D-Star bit order version of 0x55 0x2D 0x16
+8 -8
View File
@@ -41,7 +41,7 @@ CCalFM::CCalFM() :
m_frequency(0), m_frequency(0),
m_length(0), m_length(0),
m_tone(NULL), m_tone(NULL),
m_level(128*32), m_level(128 * 12),
m_transmit(false), m_transmit(false),
m_audioSeq(0), m_audioSeq(0),
m_lastState(STATE_IDLE) m_lastState(STATE_IDLE)
@@ -56,25 +56,25 @@ void CCalFM::process()
{ {
switch (m_modemState) { switch (m_modemState) {
case STATE_FMCAL10K: case STATE_FMCAL10K:
m_frequency=956U; m_frequency = 956U;
break; break;
case STATE_FMCAL12K: case STATE_FMCAL12K:
m_frequency=1039U; m_frequency = 1039U;
break; break;
case STATE_FMCAL15K: case STATE_FMCAL15K:
m_frequency=1247U; m_frequency = 1247U;
break; break;
case STATE_FMCAL20K: case STATE_FMCAL20K:
m_frequency=1633U; m_frequency = 1633U;
break; break;
case STATE_FMCAL25K: case STATE_FMCAL25K:
m_frequency=2079U; m_frequency = 2079U;
break; break;
case STATE_FMCAL30K: case STATE_FMCAL30K:
m_frequency=2495U; m_frequency = 2495U;
break; break;
default: default:
m_frequency=0; m_frequency = 0U;
break; break;
} }
+37 -17
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2009-2015 by Jonathan Naylor G4KLX * Copyright (C) 2009-2015,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -19,30 +19,50 @@
#if !defined(DSTARDEFINES_H) #if !defined(DSTARDEFINES_H)
#define DSTARDEFINES_H #define DSTARDEFINES_H
const unsigned int DSTAR_RADIO_BIT_LENGTH = 5U; // At 24 kHz sample rate const unsigned int DSTAR_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U; const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U;
const unsigned int DSTAR_HEADER_LENGTH_BITS = DSTAR_HEADER_LENGTH_BYTES * 8U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U; const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U; const unsigned int DSTAR_FEC_SECTION_LENGTH_SYMBOLS = 660U;
const unsigned int DSTAR_FEC_SECTION_LENGTH_SAMPLES = DSTAR_FEC_SECTION_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U; const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U; const unsigned int DSTAR_DATA_LENGTH_SYMBOLS = DSTAR_DATA_LENGTH_BYTES * 8U;
const unsigned int DSTAR_DATA_LENGTH_SAMPLES = DSTAR_DATA_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const uint8_t DSTAR_EOT_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned int DSTAR_END_SYNC_LENGTH_BYTES = 6U;
const unsigned int DSTAR_EOT_LENGTH_BYTES = 6U; const unsigned int DSTAR_END_SYNC_LENGTH_BITS = DSTAR_END_SYNC_LENGTH_BYTES * 8U;
const unsigned int DSTAR_EOT_LENGTH_BITS = DSTAR_EOT_LENGTH_BYTES * 8U;
const uint8_t DSTAR_DATA_SYNC_LENGTH_BYTES = 3U; const unsigned int DSTAR_FRAME_SYNC_LENGTH_BYTES = 3U;
const uint8_t DSTAR_DATA_SYNC_LENGTH_BITS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U; const unsigned int DSTAR_FRAME_SYNC_LENGTH_SYMBOLS = DSTAR_FRAME_SYNC_LENGTH_BYTES * 8U;
const unsigned int DSTAR_FRAME_SYNC_LENGTH_SAMPLES = DSTAR_FRAME_SYNC_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16}; const unsigned int DSTAR_DATA_SYNC_LENGTH_BYTES = 3U;
const unsigned int DSTAR_DATA_SYNC_LENGTH_SYMBOLS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U;
const unsigned int DSTAR_DATA_SYNC_LENGTH_SAMPLES = DSTAR_DATA_SYNC_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U; const uint8_t DSTAR_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16};
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U}; // D-Star bit order version of 0x55 0x6E 0x0A
const uint32_t DSTAR_FRAME_SYNC_DATA = 0x00557650U;
const uint32_t DSTAR_FRAME_SYNC_MASK = 0x00FFFFFFU;
const bool DSTAR_FRAME_SYNC_SYMBOLS[] = {false, true, false, true, false, true, false, true, false, true, true, true, false, true, true, false, false, true, false, true, false, false, false, false};
// D-Star bit order version of 0x55 0x2D 0x16
const uint32_t DSTAR_DATA_SYNC_DATA = 0x00AAB468U;
const uint32_t DSTAR_DATA_SYNC_MASK = 0x00FFFFFFU;
const bool DSTAR_DATA_SYNC_SYMBOLS[] = {true, false, true, false, true, false, true, false, true, false, true, true, false, true, false, false, false, true, true, false, true, false, false, false};
// D-Star bit order version of 0x55 0x55 0xC8 0x7A
const uint32_t DSTAR_END_SYNC_DATA = 0xAAAA135EU;
const uint32_t DSTAR_END_SYNC_MASK = 0xFFFFFFFFU;
const uint8_t DSTAR_END_SYNC_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
const uint8_t DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
#endif #endif
+238 -137
View File
@@ -22,18 +22,12 @@
#include "DStarRX.h" #include "DStarRX.h"
#include "Utils.h" #include "Utils.h"
const unsigned int BUFFER_LENGTH = 200U; const unsigned int MAX_FRAMES = 150U;
const uint32_t PLLMAX = 0x10000U;
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
const uint32_t INC = PLLINC / 32U;
const unsigned int MAX_SYNC_BITS = 100U * DSTAR_DATA_LENGTH_BITS;
// D-Star bit order version of 0x55 0x55 0x6E 0x0A // D-Star bit order version of 0x55 0x55 0x6E 0x0A
const uint32_t FRAME_SYNC_DATA = 0x00557650U; const uint32_t FRAME_SYNC_DATA = 0x00557650U;
const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU; const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU;
const uint8_t FRAME_SYNC_ERRS = 2U; const uint8_t FRAME_SYNC_ERRS = 1U;
// D-Star bit order version of 0x55 0x2D 0x16 // D-Star bit order version of 0x55 0x2D 0x16
const uint32_t DATA_SYNC_DATA = 0x00AAB468U; const uint32_t DATA_SYNC_DATA = 0x00AAB468U;
@@ -237,14 +231,24 @@ const uint16_t CCITT_TABLE[] = {
0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U, 0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U}; 0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U};
const uint16_t NOENDPTR = 9999U;
CDStarRX::CDStarRX() : CDStarRX::CDStarRX() :
m_pll(0U),
m_prev(false),
m_rxState(DSRXS_NONE), m_rxState(DSRXS_NONE),
m_patternBuffer(0x00U), m_bitBuffer(),
m_rxBuffer(), m_headerBuffer(),
m_rxBufferBits(0U), m_dataBuffer(),
m_dataBits(0U), m_bitPtr(0U),
m_headerPtr(0U),
m_dataPtr(0U),
m_startPtr(NOENDPTR),
m_syncPtr(NOENDPTR),
m_minSyncPtr(NOENDPTR),
m_maxSyncPtr(NOENDPTR),
m_maxFrameCorr(0),
m_maxDataCorr(0),
m_frameCount(0U),
m_countdown(0U),
m_mar(0U), m_mar(0U),
m_pathMetric(), m_pathMetric(),
m_pathMemory0(), m_pathMemory0(),
@@ -259,14 +263,20 @@ m_rssiCount(0U)
void CDStarRX::reset() void CDStarRX::reset()
{ {
m_pll = 0U; m_rxState = DSRXS_NONE;
m_prev = false; m_headerPtr = 0U;
m_rxState = DSRXS_NONE; m_dataPtr = 0U;
m_patternBuffer = 0x00U; m_bitPtr = 0U;
m_rxBufferBits = 0U; m_maxFrameCorr = 0;
m_dataBits = 0U; m_maxDataCorr = 0;
m_rssiAccum = 0U; m_startPtr = NOENDPTR;
m_rssiCount = 0U; m_syncPtr = NOENDPTR;
m_minSyncPtr = NOENDPTR;
m_maxSyncPtr = NOENDPTR;
m_frameCount = 0U;
m_countdown = 0U;
m_rssiAccum = 0U;
m_rssiCount = 0U;
} }
void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length) void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
@@ -275,125 +285,117 @@ void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t lengt
m_rssiAccum += rssi[i]; m_rssiAccum += rssi[i];
m_rssiCount++; m_rssiCount++;
bool bit = samples[i] < 0; q15_t sample = samples[i];
if (bit != m_prev) { m_bitBuffer[m_bitPtr] <<= 1;
if (m_pll < (PLLMAX / 2U)) if (sample < 0)
m_pll += INC; m_bitBuffer[m_bitPtr] |= 0x01U;
else
m_pll -= INC; m_dataBuffer[m_dataPtr] = sample;
switch (m_rxState) {
case DSRXS_HEADER:
processHeader(sample);
break;
case DSRXS_DATA:
processData();
break;
default:
processNone(sample);
break;
} }
m_prev = bit; m_dataPtr++;
if (m_dataPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_dataPtr = 0U;
m_pll += PLLINC; m_bitPtr++;
if (m_bitPtr >= DSTAR_RADIO_SYMBOL_LENGTH)
if (m_pll >= PLLMAX) { m_bitPtr = 0U;
m_pll -= PLLMAX;
switch (m_rxState) {
case DSRXS_NONE:
processNone(bit);
break;
case DSRXS_HEADER:
processHeader(bit);
break;
case DSRXS_DATA:
processData(bit);
break;
default:
break;
}
}
} }
} }
void CDStarRX::processNone(bool bit) void CDStarRX::processNone(q15_t sample)
{ {
m_patternBuffer <<= 1;
if (bit)
m_patternBuffer |= 0x01U;
// Fuzzy matching of the frame sync sequence // Fuzzy matching of the frame sync sequence
if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) { bool ret = correlateFrameSync();
DEBUG1("DStarRX: found frame sync in None"); if (ret) {
m_countdown = 5U;
::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES);
m_rxBufferBits = 0U; m_headerBuffer[m_headerPtr] = sample;
m_headerPtr++;
m_rssiAccum = 0U; m_rssiAccum = 0U;
m_rssiCount = 0U; m_rssiCount = 0U;
m_rxState = DSRXS_HEADER; m_rxState = DSRXS_HEADER;
return; return;
} }
// Exact matching of the data sync bit sequence // Fuzzy matching of the data sync bit sequence
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) { ret = correlateDataSync();
if (ret) {
DEBUG1("DStarRX: found data sync in None"); DEBUG1("DStarRX: found data sync in None");
io.setDecode(true); io.setDecode(true);
io.setADCDetection(true); io.setADCDetection(true);
// Suppress RSSI on the dummy sync message m_rxState = DSRXS_DATA;
m_rssiAccum = 0U;
m_rssiCount = 0U;
::memcpy(m_rxBuffer, DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES);
writeRSSIData(m_rxBuffer);
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
m_rxBufferBits = 0U;
m_dataBits = MAX_SYNC_BITS;
m_rxState = DSRXS_DATA;
return;
} }
} }
void CDStarRX::processHeader(bool bit) void CDStarRX::processHeader(q15_t sample)
{ {
m_patternBuffer <<= 1; if (m_countdown > 0U) {
if (bit) correlateFrameSync();
m_patternBuffer |= 0x01U; m_countdown--;
}
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit); m_headerBuffer[m_headerPtr] = sample;
m_rxBufferBits++; m_headerPtr++;
// A full FEC header // A full FEC header
if (m_rxBufferBits == DSTAR_FEC_SECTION_LENGTH_BITS) { if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH)) {
// Process the scrambling, interleaving and FEC, then return if the chcksum was correct uint8_t buffer[DSTAR_FEC_SECTION_LENGTH_BYTES];
unsigned char header[DSTAR_HEADER_LENGTH_BYTES]; samplesToBits(m_headerBuffer, DSTAR_RADIO_SYMBOL_LENGTH, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES);
bool ok = rxHeader(m_rxBuffer, header);
if (ok) { // Process the scrambling, interleaving and FEC, then return true if the chcksum was correct
uint8_t header[DSTAR_HEADER_LENGTH_BYTES];
bool ok = rxHeader(buffer, header);
if (!ok) {
// The checksum failed, return to looking for syncs
m_rxState = DSRXS_NONE;
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
} else {
io.setDecode(true); io.setDecode(true);
io.setADCDetection(true); io.setADCDetection(true);
writeRSSIHeader(header); writeRSSIHeader(header);
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
m_rxBufferBits = 0U;
m_rxState = DSRXS_DATA;
m_dataBits = MAX_SYNC_BITS;
} else {
// The checksum failed, return to looking for syncs
m_rxState = DSRXS_NONE;
} }
} }
// Ready to start the first data section
if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH)) {
m_frameCount = 0U;
m_dataPtr = 0U;
m_startPtr = 476U;
m_syncPtr = 471U;
m_maxSyncPtr = 472U;
m_minSyncPtr = 470U;
DEBUG5("DStarRX: calc start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr);
m_rxState = DSRXS_DATA;
}
} }
void CDStarRX::processData(bool bit) void CDStarRX::processData()
{ {
m_patternBuffer <<= 1;
if (bit)
m_patternBuffer |= 0x01U;
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
m_rxBufferBits++;
// Fuzzy matching of the end frame sequences // Fuzzy matching of the end frame sequences
if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) { if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_END_SYNC_MASK) ^ DSTAR_END_SYNC_DATA) <= END_SYNC_ERRS) {
DEBUG1("DStarRX: Found end sync in Data"); DEBUG1("DStarRX: Found end sync in Data");
io.setDecode(false); io.setDecode(false);
@@ -401,35 +403,24 @@ void CDStarRX::processData(bool bit)
serial.writeDStarEOT(); serial.writeDStarEOT();
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
m_rxState = DSRXS_NONE; m_rxState = DSRXS_NONE;
return; return;
} }
// Fuzzy matching of the data sync bit sequence // Fuzzy matching of the data sync bit sequence
bool syncSeen = false; if (m_minSyncPtr < m_maxSyncPtr) {
if (m_rxBufferBits >= (DSTAR_DATA_LENGTH_BITS - 3U)) { if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr)
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) { correlateDataSync();
m_rxBufferBits = DSTAR_DATA_LENGTH_BITS; } else {
m_dataBits = MAX_SYNC_BITS; if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr)
syncSeen = true; correlateDataSync();
}
} }
// Check to see if the sync is arriving late // We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS && !syncSeen) { if (m_frameCount >= MAX_FRAMES) {
for (uint8_t i = 1U; i <= 3U; i++) {
uint32_t syncMask = DATA_SYNC_MASK >> i;
uint32_t syncData = DATA_SYNC_DATA >> i;
if (countBits32((m_patternBuffer & syncMask) ^ syncData) <= DATA_SYNC_ERRS) {
m_rxBufferBits -= i;
break;
}
}
}
m_dataBits--;
if (m_dataBits == 0U) {
DEBUG1("DStarRX: data sync timed out, lost lock"); DEBUG1("DStarRX: data sync timed out, lost lock");
io.setDecode(false); io.setDecode(false);
@@ -437,24 +428,35 @@ void CDStarRX::processData(bool bit)
serial.writeDStarLost(); serial.writeDStarLost();
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
m_rxState = DSRXS_NONE; m_rxState = DSRXS_NONE;
return; return;
} }
// Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen // Send a data frame to the host if the required number of bits have been received
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS) { if (m_dataPtr == m_maxSyncPtr) {
if (syncSeen) { uint8_t buffer[DSTAR_DATA_LENGTH_BYTES + 2U];
m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U]; samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES);
m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
writeRSSIData(m_rxBuffer);
} else {
serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES);
}
// Start the next frame if ((m_frameCount % 21U) == 0U) {
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); if (m_frameCount == 0U) {
m_rxBufferBits = 0U; buffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
buffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
buffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
DEBUG5("DStarRX: found start/sync/max/min", m_startPtr, m_syncPtr, m_maxSyncPtr, m_minSyncPtr);
}
writeRSSIData(buffer);
} else {
serial.writeDStarData(buffer, DSTAR_DATA_LENGTH_BYTES);
}
m_frameCount++;
m_maxFrameCorr = 0;
m_maxDataCorr = 0;
} }
} }
@@ -500,6 +502,105 @@ void CDStarRX::writeRSSIData(unsigned char* data)
m_rssiCount = 0U; m_rssiCount = 0U;
} }
bool CDStarRX::correlateFrameSync()
{
if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_FRAME_SYNC_MASK) ^ DSTAR_FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_FRAME_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
q31_t corr = 0;
for (uint8_t i = 0U; i < DSTAR_FRAME_SYNC_LENGTH_SYMBOLS; i++) {
q15_t val = m_dataBuffer[ptr];
if (DSTAR_FRAME_SYNC_SYMBOLS[i])
corr -= val;
else
corr += val;
ptr += DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
}
if (corr > m_maxFrameCorr) {
m_maxFrameCorr = corr;
m_headerPtr = 0U;
return true;
}
}
return false;
}
bool CDStarRX::correlateDataSync()
{
uint8_t maxErrs = 0U;
if (m_rxState == DSRXS_DATA)
maxErrs = DATA_SYNC_ERRS;
if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_DATA_SYNC_MASK) ^ DSTAR_DATA_SYNC_DATA) <= maxErrs) {
uint16_t ptr = m_dataPtr + DSTAR_DATA_LENGTH_SAMPLES - DSTAR_DATA_SYNC_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
q31_t corr = 0;
for (uint8_t i = 0U; i < DSTAR_DATA_SYNC_LENGTH_SYMBOLS; i++) {
q15_t val = m_dataBuffer[ptr];
if (DSTAR_DATA_SYNC_SYMBOLS[i])
corr -= val;
else
corr += val;
ptr += DSTAR_RADIO_SYMBOL_LENGTH;
if (ptr >= DSTAR_DATA_LENGTH_SAMPLES)
ptr -= DSTAR_DATA_LENGTH_SAMPLES;
}
if (corr > m_maxDataCorr) {
m_maxDataCorr = corr;
m_frameCount = 0U;
m_syncPtr = m_dataPtr;
m_startPtr = m_dataPtr + DSTAR_RADIO_SYMBOL_LENGTH;
if (m_startPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_startPtr -= DSTAR_DATA_LENGTH_SAMPLES;
m_maxSyncPtr = m_syncPtr + 1U;
if (m_maxSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_maxSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES;
m_minSyncPtr = m_syncPtr + DSTAR_DATA_LENGTH_SAMPLES - 1U;
if (m_minSyncPtr >= DSTAR_DATA_LENGTH_SAMPLES)
m_minSyncPtr -= DSTAR_DATA_LENGTH_SAMPLES;
return true;
}
}
return false;
}
void CDStarRX::samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit)
{
for (uint16_t i = 0U; i < count; i++) {
q15_t sample = inBuffer[start];
if (sample < 0)
WRITE_BIT2(outBuffer, i, true);
else
WRITE_BIT2(outBuffer, i, false);
start += DSTAR_RADIO_SYMBOL_LENGTH;
if (start >= limit)
start -= limit;
}
}
bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out) bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out)
{ {
int i; int i;
+20 -9
View File
@@ -37,13 +37,21 @@ public:
void reset(); void reset();
private: private:
uint32_t m_pll;
bool m_prev;
DSRX_STATE m_rxState; DSRX_STATE m_rxState;
uint32_t m_patternBuffer; uint32_t m_bitBuffer[DSTAR_RADIO_SYMBOL_LENGTH];
uint8_t m_rxBuffer[100U]; q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH];
unsigned int m_rxBufferBits; q15_t m_dataBuffer[DSTAR_DATA_LENGTH_SAMPLES];
unsigned int m_dataBits; uint16_t m_bitPtr;
uint16_t m_headerPtr;
uint16_t m_dataPtr;
uint16_t m_startPtr;
uint16_t m_syncPtr;
uint16_t m_minSyncPtr;
uint16_t m_maxSyncPtr;
q31_t m_maxFrameCorr;
q31_t m_maxDataCorr;
uint16_t m_frameCount;
uint8_t m_countdown;
unsigned int m_mar; unsigned int m_mar;
int m_pathMetric[4U]; int m_pathMetric[4U];
unsigned int m_pathMemory0[42U]; unsigned int m_pathMemory0[42U];
@@ -54,9 +62,12 @@ private:
uint32_t m_rssiAccum; uint32_t m_rssiAccum;
uint16_t m_rssiCount; uint16_t m_rssiCount;
void processNone(bool bit); void processNone(q15_t sample);
void processHeader(bool bit); void processHeader(q15_t sample);
void processData(bool bit); void processData();
bool correlateFrameSync();
bool correlateDataSync();
void samplesToBits(const q15_t* inBuffer, uint16_t start, uint16_t count, uint8_t* outBuffer, uint16_t limit);
void writeRSSIHeader(unsigned char* header); void writeRSSIHeader(unsigned char* header);
void writeRSSIData(unsigned char* data); void writeRSSIData(unsigned char* data);
bool rxHeader(uint8_t* in, uint8_t* out); bool rxHeader(uint8_t* in, uint8_t* out);
+7 -7
View File
@@ -198,7 +198,7 @@ m_txDelay(60U) // 100ms
{ {
::memset(m_modState, 0x00U, 20U * sizeof(q15_t)); ::memset(m_modState, 0x00U, 20U * sizeof(q15_t));
m_modFilter.L = DSTAR_RADIO_BIT_LENGTH; m_modFilter.L = DSTAR_RADIO_SYMBOL_LENGTH;
m_modFilter.phaseLength = GAUSSIAN_0_35_FILTER_PHASE_LEN; m_modFilter.phaseLength = GAUSSIAN_0_35_FILTER_PHASE_LEN;
m_modFilter.pCoeffs = GAUSSIAN_0_35_FILTER; m_modFilter.pCoeffs = GAUSSIAN_0_35_FILTER;
m_modFilter.pState = m_modState; m_modFilter.pState = m_modState;
@@ -252,8 +252,8 @@ void CDStarTX::process()
m_buffer.get(); m_buffer.get();
for (uint8_t j = 0U; j < 3U; j++) { for (uint8_t j = 0U; j < 3U; j++) {
for (uint8_t i = 0U; i < DSTAR_EOT_LENGTH_BYTES; i++) for (uint8_t i = 0U; i < DSTAR_END_SYNC_LENGTH_BYTES; i++)
m_poBuffer[m_poLen++] = DSTAR_EOT_BYTES[i]; m_poBuffer[m_poLen++] = DSTAR_END_SYNC_BYTES[i];
} }
m_poPtr = 0U; m_poPtr = 0U;
@@ -262,11 +262,11 @@ void CDStarTX::process()
if (m_poLen > 0U) { if (m_poLen > 0U) {
uint16_t space = io.getSpace(); uint16_t space = io.getSpace();
while (space > (8U * DSTAR_RADIO_BIT_LENGTH)) { while (space > (8U * DSTAR_RADIO_SYMBOL_LENGTH)) {
uint8_t c = m_poBuffer[m_poPtr++]; uint8_t c = m_poBuffer[m_poPtr++];
writeByte(c); writeByte(c);
space -= 8U * DSTAR_RADIO_BIT_LENGTH; space -= 8U * DSTAR_RADIO_SYMBOL_LENGTH;
if (m_poPtr >= m_poLen) { if (m_poPtr >= m_poLen) {
m_poPtr = 0U; m_poPtr = 0U;
@@ -412,7 +412,7 @@ void CDStarTX::txHeader(const uint8_t* in, uint8_t* out) const
void CDStarTX::writeByte(uint8_t c) void CDStarTX::writeByte(uint8_t c)
{ {
q15_t inBuffer[8U]; q15_t inBuffer[8U];
q15_t outBuffer[DSTAR_RADIO_BIT_LENGTH * 8U]; q15_t outBuffer[DSTAR_RADIO_SYMBOL_LENGTH * 8U];
uint8_t mask = 0x01U; uint8_t mask = 0x01U;
@@ -427,7 +427,7 @@ void CDStarTX::writeByte(uint8_t c)
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 8U); ::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 8U);
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_BIT_LENGTH * 8U); io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_SYMBOL_LENGTH * 8U);
} }
void CDStarTX::setTXDelay(uint8_t delay) void CDStarTX::setTXDelay(uint8_t delay)
+66 -16
View File
@@ -40,17 +40,19 @@ m_hangTimer(),
m_filterStage1( 724, 1448, 724, 32768, -37895, 21352),//3rd order Cheby Filter 300 to 2700Hz, 0.2dB passband ripple, sampling rate 24kHz m_filterStage1( 724, 1448, 724, 32768, -37895, 21352),//3rd order Cheby Filter 300 to 2700Hz, 0.2dB passband ripple, sampling rate 24kHz
m_filterStage2(32768, 0,-32768, 32768, -50339, 19052), m_filterStage2(32768, 0,-32768, 32768, -50339, 19052),
m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460), m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460),
m_preemphasis(32768, 13967, 0, 32768, -18801, 0),//75µS 24kHz sampling rate
m_deemphasis (32768, -18801, 0, 32768, 13967, 0),//75µS 24kHz sampling rate
m_blanking(), m_blanking(),
m_useCOS(true), m_useCOS(true),
m_cosInvert(false), m_cosInvert(false),
m_rfAudioBoost(1U), m_rfAudioBoost(1U),
m_downsampler(128)//Size might need adjustement m_downsampler(128U),//Size might need adjustement
m_rxLevel(1),
m_inputRB(4800U), // 200ms of audio
m_outputRB(2400U) // 100ms of audio
{ {
insertDelay(100U);
} }
void CFM::samples(bool cos, q15_t* samples, uint8_t length) void CFM::samples(bool cos, const q15_t* samples, uint8_t length)
{ {
if (m_useCOS) { if (m_useCOS) {
if (m_cosInvert) if (m_cosInvert)
@@ -63,10 +65,17 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
uint8_t i = 0U; uint8_t i = 0U;
for (; i < length; i++) { for (; i < length; i++) {
q15_t currentSample = samples[i];//save to a local variable to avoid indirection on every access // ARMv7-M has hardware integer division
q15_t currentSample = q15_t((q31_t(samples[i]) << 8) / m_rxLevel);
uint8_t ctcssState = m_ctcssRX.process(currentSample); uint8_t ctcssState = m_ctcssRX.process(currentSample);
if (!m_useCOS) {
// Delay the audio by 100ms to better match the CTCSS detector output
m_inputRB.put(currentSample);
m_inputRB.get(currentSample);
}
if (CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) { if (CTCSS_NOT_READY(ctcssState) && m_modemState != STATE_FM) {
//Not enough samples to determine if you have CTCSS, just carry on //Not enough samples to determine if you have CTCSS, just carry on
continue; continue;
@@ -90,8 +99,7 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
} }
// Only let audio through when relaying audio // Only let audio through when relaying audio
if (m_state == FS_RELAYING || m_state == FS_KERCHUNK) { if (m_state == FS_RELAYING || m_state == FS_KERCHUNK) {
// currentSample = m_deemphasis.filter(currentSample);
// m_downsampler.addSample(currentSample); // m_downsampler.addSample(currentSample);
currentSample = m_blanking.process(currentSample); currentSample = m_blanking.process(currentSample);
currentSample *= m_rfAudioBoost; currentSample *= m_rfAudioBoost;
@@ -114,19 +122,18 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
currentSample = m_filterStage3.filter(m_filterStage2.filter(m_filterStage1.filter(currentSample))); currentSample = m_filterStage3.filter(m_filterStage2.filter(m_filterStage1.filter(currentSample)));
// currentSample = m_preemphasis.filter(currentSample);
currentSample += m_ctcssTX.getAudio(); currentSample += m_ctcssTX.getAudio();
samples[i] = currentSample; if (m_modemState == STATE_FM)
m_outputRB.put(currentSample);
} }
if (m_modemState == STATE_FM)
io.write(STATE_FM, samples, i);//only write the actual number of processed samples to IO
} }
void CFM::process() void CFM::process()
{ {
q15_t sample;
while (io.getSpace() >= 3U && m_outputRB.get(sample))
io.write(STATE_FM, &sample, 1U);
} }
void CFM::reset() void CFM::reset()
@@ -144,6 +151,8 @@ void CFM::reset()
m_rfAck.stop(); m_rfAck.stop();
m_callsign.stop(); m_callsign.stop();
m_timeoutTone.stop(); m_timeoutTone.stop();
m_outputRB.reset();
} }
uint8_t CFM::setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch) uint8_t CFM::setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch)
@@ -174,7 +183,7 @@ uint8_t CFM::setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_
return m_rfAck.setParams(rfAck, speed, frequency, level, level); return m_rfAck.setParams(rfAck, speed, frequency, level, level);
} }
uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel) uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel)
{ {
m_useCOS = useCOS; m_useCOS = useCOS;
m_cosInvert = cosInvert; m_cosInvert = cosInvert;
@@ -188,7 +197,9 @@ uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFreque
m_timeoutTone.setParams(timeoutLevel); m_timeoutTone.setParams(timeoutLevel);
m_blanking.setParams(maxDev, timeoutLevel); m_blanking.setParams(maxDev, timeoutLevel);
uint8_t ret = m_ctcssRX.setParams(ctcssFrequency, ctcssThreshold, rxLevel); m_rxLevel = rxLevel; //q15_t(255)/q15_t(rxLevel >> 1);
uint8_t ret = m_ctcssRX.setParams(ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold);
if (ret != 0U) if (ret != 0U)
return ret; return ret;
@@ -224,7 +235,7 @@ void CFM::stateMachine(bool validSignal)
} }
if (m_state == FS_LISTENING && m_modemState == STATE_FM) { if (m_state == FS_LISTENING && m_modemState == STATE_FM) {
if (!m_callsign.isRunning() && !m_rfAck.isRunning()) { if (!m_callsign.isWanted() && !m_rfAck.isWanted()) {
DEBUG1("Change to STATE_IDLE"); DEBUG1("Change to STATE_IDLE");
m_modemState = STATE_IDLE; m_modemState = STATE_IDLE;
m_callsignTimer.stop(); m_callsignTimer.stop();
@@ -264,10 +275,15 @@ void CFM::listeningState(bool validSignal)
sendCallsign(); sendCallsign();
} }
insertSilence(50U);
beginRelaying(); beginRelaying();
m_callsignTimer.start(); m_callsignTimer.start();
io.setDecode(true);
io.setADCDetection(true);
DEBUG1("Change to STATE_FM"); DEBUG1("Change to STATE_FM");
m_modemState = STATE_FM; m_modemState = STATE_FM;
} }
@@ -286,6 +302,9 @@ void CFM::kerchunkState(bool validSignal)
} }
} }
} else { } else {
io.setDecode(false);
io.setADCDetection(false);
DEBUG1("State to LISTENING"); DEBUG1("State to LISTENING");
m_state = FS_LISTENING; m_state = FS_LISTENING;
m_kerchunkTimer.stop(); m_kerchunkTimer.stop();
@@ -306,6 +325,9 @@ void CFM::relayingState(bool validSignal)
m_timeoutTone.start(); m_timeoutTone.start();
} }
} else { } else {
io.setDecode(false);
io.setADCDetection(false);
DEBUG1("State to RELAYING_WAIT"); DEBUG1("State to RELAYING_WAIT");
m_state = FS_RELAYING_WAIT; m_state = FS_RELAYING_WAIT;
m_ackDelayTimer.start(); m_ackDelayTimer.start();
@@ -320,6 +342,9 @@ void CFM::relayingState(bool validSignal)
void CFM::relayingWaitState(bool validSignal) void CFM::relayingWaitState(bool validSignal)
{ {
if (validSignal) { if (validSignal) {
io.setDecode(true);
io.setADCDetection(true);
DEBUG1("State to RELAYING"); DEBUG1("State to RELAYING");
m_state = FS_RELAYING; m_state = FS_RELAYING;
m_ackDelayTimer.stop(); m_ackDelayTimer.stop();
@@ -355,6 +380,9 @@ void CFM::relayingWaitState(bool validSignal)
void CFM::hangState(bool validSignal) void CFM::hangState(bool validSignal)
{ {
if (validSignal) { if (validSignal) {
io.setDecode(true);
io.setADCDetection(true);
DEBUG1("State to RELAYING"); DEBUG1("State to RELAYING");
m_state = FS_RELAYING; m_state = FS_RELAYING;
DEBUG1("Stop ack"); DEBUG1("Stop ack");
@@ -382,6 +410,9 @@ void CFM::hangState(bool validSignal)
void CFM::timeoutState(bool validSignal) void CFM::timeoutState(bool validSignal)
{ {
if (!validSignal) { if (!validSignal) {
io.setDecode(false);
io.setADCDetection(false);
DEBUG1("State to TIMEOUT_WAIT"); DEBUG1("State to TIMEOUT_WAIT");
m_state = FS_TIMEOUT_WAIT; m_state = FS_TIMEOUT_WAIT;
m_ackDelayTimer.start(); m_ackDelayTimer.start();
@@ -396,6 +427,9 @@ void CFM::timeoutState(bool validSignal)
void CFM::timeoutWaitState(bool validSignal) void CFM::timeoutWaitState(bool validSignal)
{ {
if (validSignal) { if (validSignal) {
io.setDecode(true);
io.setADCDetection(true);
DEBUG1("State to TIMEOUT"); DEBUG1("State to TIMEOUT");
m_state = FS_TIMEOUT; m_state = FS_TIMEOUT;
m_ackDelayTimer.stop(); m_ackDelayTimer.stop();
@@ -438,3 +472,19 @@ void CFM::beginRelaying()
m_timeoutTimer.start(); m_timeoutTimer.start();
m_ackMinTimer.start(); m_ackMinTimer.start();
} }
void CFM::insertDelay(uint16_t ms)
{
uint32_t nSamples = ms * 24U;
for (uint32_t i = 0U; i < nSamples; i++)
m_inputRB.put(0);
}
void CFM::insertSilence(uint16_t ms)
{
uint32_t nSamples = ms * 24U;
for (uint32_t i = 0U; i < nSamples; i++)
m_outputRB.put(0);
}
+9 -4
View File
@@ -27,6 +27,7 @@
#include "FMTimeout.h" #include "FMTimeout.h"
#include "FMKeyer.h" #include "FMKeyer.h"
#include "FMTimer.h" #include "FMTimer.h"
#include "FMRB.h"
#include "FMDirectForm1.h" #include "FMDirectForm1.h"
#include "FMDownsampler.h" #include "FMDownsampler.h"
@@ -47,7 +48,7 @@ class CFM {
public: public:
CFM(); CFM();
void samples(bool cos, q15_t* samples, uint8_t length); void samples(bool cos, const q15_t* samples, uint8_t length);
void process(); void process();
@@ -55,7 +56,7 @@ public:
uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch); uint8_t setCallsign(const char* callsign, uint8_t speed, uint16_t frequency, uint8_t time, uint8_t holdoff, uint8_t highLevel, uint8_t lowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch);
uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level); uint8_t setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_t minTime, uint16_t delay, uint8_t level);
uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel); uint8_t setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFrequency, uint8_t ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
private: private:
CFMKeyer m_callsign; CFMKeyer m_callsign;
@@ -77,13 +78,14 @@ private:
CFMDirectFormI m_filterStage1; CFMDirectFormI m_filterStage1;
CFMDirectFormI m_filterStage2; CFMDirectFormI m_filterStage2;
CFMDirectFormI m_filterStage3; CFMDirectFormI m_filterStage3;
CFMDirectFormI m_preemphasis;
CFMDirectFormI m_deemphasis;
CFMBlanking m_blanking; CFMBlanking m_blanking;
bool m_useCOS; bool m_useCOS;
bool m_cosInvert; bool m_cosInvert;
q15_t m_rfAudioBoost; q15_t m_rfAudioBoost;
CFMDownsampler m_downsampler; CFMDownsampler m_downsampler;
q15_t m_rxLevel;
CFMRB m_inputRB;
CFMRB m_outputRB;
void stateMachine(bool validSignal); void stateMachine(bool validSignal);
void listeningState(bool validSignal); void listeningState(bool validSignal);
@@ -98,6 +100,9 @@ private:
void sendCallsign(); void sendCallsign();
void beginRelaying(); void beginRelaying();
void insertDelay(uint16_t ms);
void insertSilence(uint16_t ms);
}; };
#endif #endif
+15 -23
View File
@@ -82,19 +82,17 @@ const uint16_t N = 24000U / 4U;
CFMCTCSSRX::CFMCTCSSRX() : CFMCTCSSRX::CFMCTCSSRX() :
m_coeffDivTwo(0), m_coeffDivTwo(0),
m_threshold(0), m_highThreshold(0),
m_lowThreshold(0),
m_count(0U), m_count(0U),
m_q0(0), m_q0(0),
m_q1(0), m_q1(0),
m_result(CTS_NONE), m_result(CTS_NONE)
m_rxLevelInverse(1)
{ {
} }
uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t threshold, uint8_t level) uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold)
{ {
m_rxLevelInverse = q15Division(65535, q15_t(level * 128));
m_coeffDivTwo = 0; m_coeffDivTwo = 0;
for (uint8_t i = 0U; i < CTCSS_TABLE_DATA_LEN; i++) { for (uint8_t i = 0U; i < CTCSS_TABLE_DATA_LEN; i++) {
@@ -107,14 +105,16 @@ uint8_t CFMCTCSSRX::setParams(uint8_t frequency, uint8_t threshold, uint8_t leve
if (m_coeffDivTwo == 0) if (m_coeffDivTwo == 0)
return 4U; return 4U;
m_threshold = q31_t(threshold); m_highThreshold = q31_t(highThreshold);
m_lowThreshold = q31_t(lowThreshold);
return 0U; return 0U;
} }
uint8_t CFMCTCSSRX::process(q15_t sample) uint8_t CFMCTCSSRX::process(q15_t sample)
{ {
q31_t sample31 = q31_t(sample) * m_rxLevelInverse; //get more dynamic into the decoder by multiplying the sample by 1.5
q31_t sample31 = q31_t(sample) + (q31_t(sample) >> 1);
m_result &= ~CTS_READY; m_result &= ~CTS_READY;
@@ -150,14 +150,19 @@ uint8_t CFMCTCSSRX::process(q15_t sample)
q31_t value = t2 + t4 - t9; q31_t value = t2 + t4 - t9;
bool previousCTCSSValid = CTCSS_VALID(m_result); bool previousCTCSSValid = CTCSS_VALID(m_result);
q31_t threshold = m_highThreshold;
if (previousCTCSSValid)
threshold = m_lowThreshold;
m_result |= CTS_READY; m_result |= CTS_READY;
if (value >= m_threshold) if (value >= threshold)
m_result |= CTS_VALID; m_result |= CTS_VALID;
else else
m_result &= ~CTS_VALID; m_result &= ~CTS_VALID;
if (previousCTCSSValid != CTCSS_VALID(m_result)) if (previousCTCSSValid != CTCSS_VALID(m_result))
DEBUG4("CTCSS Value / Threshold / Valid", value, m_threshold, CTCSS_VALID(m_result)); DEBUG4("CTCSS Value / Threshold / Valid", value, threshold, CTCSS_VALID(m_result));
m_count = 0U; m_count = 0U;
m_q0 = 0; m_q0 = 0;
@@ -174,16 +179,3 @@ void CFMCTCSSRX::reset()
m_result = CTS_NONE; m_result = CTS_NONE;
m_count = 0U; m_count = 0U;
} }
//Taken from https://en.wikipedia.org/wiki/Q_(number_format)#Division
q15_t CFMCTCSSRX::q15Division(q15_t a, q15_t divisor)
{
q31_t a31 = q31_t(a) << 16;
if (((a >> 31) & 1) == ((divisor >> 15) & 1))
a31 += divisor >> 1;
else
a31 -= divisor >> 1;
return a31 / divisor;
}
+3 -5
View File
@@ -34,7 +34,7 @@ class CFMCTCSSRX {
public: public:
CFMCTCSSRX(); CFMCTCSSRX();
uint8_t setParams(uint8_t frequency, uint8_t threshold, uint8_t level); uint8_t setParams(uint8_t frequency, uint8_t highThreshold, uint8_t lowThreshold);
uint8_t process(q15_t sample); uint8_t process(q15_t sample);
@@ -42,14 +42,12 @@ public:
private: private:
q63_t m_coeffDivTwo; q63_t m_coeffDivTwo;
q31_t m_threshold; q31_t m_highThreshold;
q31_t m_lowThreshold;
uint16_t m_count; uint16_t m_count;
q31_t m_q0; q31_t m_q0;
q31_t m_q1; q31_t m_q1;
uint8_t m_result; uint8_t m_result;
q15_t m_rxLevelInverse;
q15_t q15Division(q15_t a, q15_t divisor);
}; };
#endif #endif
+2 -2
View File
@@ -16,8 +16,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#if !defined(FMRB_H) #if !defined(FMDOWNSAMPLERB_H)
#define FMRB_H #define FMDOWNSAMPLERB_H
#if defined(STM32F4XX) #if defined(STM32F4XX)
#include "stm32f4xx.h" #include "stm32f4xx.h"
+1 -1
View File
@@ -40,4 +40,4 @@ private:
uint8_t m_downSampleIndex; uint8_t m_downSampleIndex;
}; };
#endif #endif
+5
View File
@@ -205,6 +205,11 @@ void CFMKeyer::stop()
m_audioPos = 0U; m_audioPos = 0U;
} }
bool CFMKeyer::isWanted() const
{
return m_wanted;
}
bool CFMKeyer::isRunning() const bool CFMKeyer::isRunning() const
{ {
return m_poPos > 0U || m_dotPos > 0U || m_audioPos > 0U; return m_poPos > 0U || m_dotPos > 0U || m_audioPos > 0U;
+2
View File
@@ -35,6 +35,8 @@ public:
bool isRunning() const; bool isRunning() const;
bool isWanted() const;
private: private:
bool m_wanted; bool m_wanted;
uint8_t m_poBuffer[1000U]; uint8_t m_poBuffer[1000U];
+110
View File
@@ -0,0 +1,110 @@
/*
TX fifo control - Copyright (C) KI6ZUM 2015
Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "FMRB.h"
CFMRB::CFMRB(uint16_t length) :
m_length(length),
m_head(0U),
m_tail(0U),
m_full(false),
m_overflow(false)
{
m_samples = new q15_t[length];
}
uint16_t CFMRB::getSpace() const
{
uint16_t n = 0U;
if (m_tail == m_head)
n = m_full ? 0U : m_length;
else if (m_tail < m_head)
n = m_length - m_head + m_tail;
else
n = m_tail - m_head;
if (n > m_length)
n = 0U;
return n;
}
uint16_t CFMRB::getData() const
{
if (m_tail == m_head)
return m_full ? m_length : 0U;
else if (m_tail < m_head)
return m_head - m_tail;
else
return m_length - m_tail + m_head;
}
bool CFMRB::put(q15_t sample)
{
if (m_full) {
m_overflow = true;
return false;
}
m_samples[m_head] = sample;
m_head++;
if (m_head >= m_length)
m_head = 0U;
if (m_head == m_tail)
m_full = true;
return true;
}
bool CFMRB::get(q15_t& sample)
{
if (m_head == m_tail && !m_full)
return false;
sample = m_samples[m_tail];
m_full = false;
m_tail++;
if (m_tail >= m_length)
m_tail = 0U;
return true;
}
bool CFMRB::hasOverflowed()
{
bool overflow = m_overflow;
m_overflow = false;
return overflow;
}
void CFMRB::reset()
{
m_head = 0U;
m_tail = 0U;
m_full = false;
m_overflow = false;
}
+72
View File
@@ -0,0 +1,72 @@
/*
Serial fifo control - Copyright (C) KI6ZUM 2015
Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#if !defined(FMRB_H)
#define FMRB_H
#if defined(STM32F4XX)
#include "stm32f4xx.h"
#elif defined(STM32F7XX)
#include "stm32f7xx.h"
#elif defined(STM32F105xC)
#include "stm32f1xx.h"
#include <cstddef>
#else
#include <Arduino.h>
#endif
#if defined(__SAM3X8E__) || defined(STM32F105xC)
#define ARM_MATH_CM3
#elif defined(STM32F7XX)
#define ARM_MATH_CM7
#elif defined(STM32F4XX) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define ARM_MATH_CM4
#else
#error "Unknown processor type"
#endif
#include <arm_math.h>
class CFMRB {
public:
CFMRB(uint16_t length);
uint16_t getSpace() const;
uint16_t getData() const;
bool put(q15_t sample);
bool get(q15_t& sample);
bool hasOverflowed();
void reset();
private:
uint16_t m_length;
volatile q15_t* m_samples;
volatile uint16_t m_head;
volatile uint16_t m_tail;
volatile bool m_full;
bool m_overflow;
};
#endif
+1 -1
View File
@@ -155,7 +155,7 @@ LDFLAGS_F722 =-T stm32f722_link.ld $(MCFLAGS_F7) --specs=nosys.specs $(INCLUDES_
# Common flags # Common flags
CFLAGS=-Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS CFLAGS=-Os -ffunction-sections -fdata-sections -fno-builtin -Wno-implicit -DCUSTOM_NEW -DNO_EXCEPTIONS
CXXFLAGS=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS CXXFLAGS=-Os -fno-exceptions -ffunction-sections -fdata-sections -fno-builtin -fno-rtti -DCUSTOM_NEW -DNO_EXCEPTIONS
LDFLAGS=-Os --specs=nano.specs LDFLAGS=-Os --specs=nano.specs -Wl,-Map=bin/mmdvm.map
# Build Rules # Build Rules
.PHONY: all release dis pi pi-f722 f4m nucleo f767 dvm drcc_nqf clean .PHONY: all release dis pi pi-f722 f4m nucleo f767 dvm drcc_nqf clean
+3 -6
View File
@@ -54,7 +54,7 @@ m_poBuffer(),
m_poLen(0U), m_poLen(0U),
m_poPtr(0U), m_poPtr(0U),
m_txDelay(240U), // 200ms m_txDelay(240U), // 200ms
m_txHang(6000U), // 5s m_txHang(3000U), // 5s
m_txCount(0U) m_txCount(0U)
{ {
::memset(m_modState, 0x00U, 16U * sizeof(q15_t)); ::memset(m_modState, 0x00U, 16U * sizeof(q15_t));
@@ -72,10 +72,7 @@ m_txCount(0U)
void CNXDNTX::process() void CNXDNTX::process()
{ {
if (m_buffer.getData() == 0U && m_poLen == 0U && m_txCount == 0U) if (m_poLen == 0U && m_buffer.getData() > 0U) {
return;
if (m_poLen == 0U) {
if (!m_tx) { if (!m_tx) {
for (uint16_t i = 0U; i < m_txDelay; i++) for (uint16_t i = 0U; i < m_txDelay; i++)
m_poBuffer[m_poLen++] = NXDN_SYNC; m_poBuffer[m_poLen++] = NXDN_SYNC;
@@ -200,5 +197,5 @@ uint8_t CNXDNTX::getSpace() const
void CNXDNTX::setParams(uint8_t txHang) void CNXDNTX::setParams(uint8_t txHang)
{ {
m_txHang = txHang * 1200U; m_txHang = txHang * 600U;
} }
+1 -4
View File
@@ -70,10 +70,7 @@ m_txCount(0U)
void CP25TX::process() void CP25TX::process()
{ {
if (m_buffer.getData() == 0U && m_poLen == 0U && m_txCount == 0U) if (m_poLen == 0U && m_buffer.getData() > 0U) {
return;
if (m_poLen == 0U) {
if (!m_tx) { if (!m_tx) {
for (uint16_t i = 0U; i < m_txDelay; i++) for (uint16_t i = 0U; i < m_txDelay; i++)
m_poBuffer[m_poLen++] = P25_START_SYNC; m_poBuffer[m_poLen++] = P25_START_SYNC;
+15 -15
View File
@@ -103,7 +103,7 @@ const uint8_t MMDVM_DEBUG5 = 0xF5U;
#define HW_TYPE "MMDVM" #define HW_TYPE "MMDVM"
#endif #endif
#define DESCRIPTION "20200506 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)" #define DESCRIPTION "20200520 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)"
#if defined(GITVERSION) #if defined(GITVERSION)
#define concat(h, a, b, c) h " " a " " b " GitID #" c "" #define concat(h, a, b, c) h " " a " " b " GitID #" c ""
@@ -417,27 +417,28 @@ uint8_t CSerialPort::setFMParams2(const uint8_t* data, uint8_t length)
uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length) uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length)
{ {
if (length < 11U) if (length < 12U)
return 4U; return 4U;
uint16_t timeout = data[0U] * 5U; uint16_t timeout = data[0U] * 5U;
uint8_t timeoutLevel = data[1U]; uint8_t timeoutLevel = data[1U];
uint8_t ctcssFrequency = data[2U]; uint8_t ctcssFrequency = data[2U];
uint8_t ctcssThreshold = data[3U]; uint8_t ctcssHighThreshold = data[3U];
uint8_t ctcssLevel = data[4U]; uint8_t ctcssLowThreshold = data[4U];
uint8_t ctcssLevel = data[5U];
uint8_t kerchunkTime = data[5U]; uint8_t kerchunkTime = data[6U];
uint8_t hangTime = data[6U]; uint8_t hangTime = data[7U];
bool useCOS = (data[7U] & 0x01U) == 0x01U; bool useCOS = (data[8U] & 0x01U) == 0x01U;
bool cosInvert = (data[7U] & 0x02U) == 0x02U; bool cosInvert = (data[8U] & 0x02U) == 0x02U;
uint8_t rfAudioBoost = data[8U]; uint8_t rfAudioBoost = data[9U];
uint8_t maxDev = data[9U]; uint8_t maxDev = data[10U];
uint8_t rxLevel = data[10U]; uint8_t rxLevel = data[11U];
return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssThreshold, ctcssLevel, kerchunkTime, hangTime, useCOS, cosInvert, rfAudioBoost, maxDev, rxLevel); return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, hangTime, useCOS, cosInvert, rfAudioBoost, maxDev, rxLevel);
} }
uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length) uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
@@ -591,8 +592,7 @@ void CSerialPort::process()
m_buffer[0U] = c; m_buffer[0U] = c;
m_ptr = 1U; m_ptr = 1U;
m_len = 0U; m_len = 0U;
} } else {
else {
m_ptr = 0U; m_ptr = 0U;
m_len = 0U; m_len = 0U;
} }
+1 -1
View File
@@ -906,7 +906,7 @@ int CSerialPort::availableForWriteInt(uint8_t n)
#if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER) #if defined(STM32F4_NUCLEO) && defined(STM32F4_NUCLEO_ARDUINO_HEADER)
return AvailForWriteUSART1(); return AvailForWriteUSART1();
#elif defined(DRCC_DVM) #elif defined(DRCC_DVM)
AvailForWriteUSART2(); return AvailForWriteUSART2();
#else #else
return AvailForWriteUART5(); return AvailForWriteUART5();
#endif #endif
-4
View File
@@ -66,9 +66,6 @@ m_txCount(0U)
void CYSFTX::process() void CYSFTX::process()
{ {
if (m_buffer.getData() == 0U && m_poLen == 0U && m_txCount == 0U)
return;
// If we have YSF data to transmit, do so. // If we have YSF data to transmit, do so.
if (m_poLen == 0U && m_buffer.getData() > 0U) { if (m_poLen == 0U && m_buffer.getData() > 0U) {
if (!m_tx) { if (!m_tx) {
@@ -191,4 +188,3 @@ void CYSFTX::setParams(bool on, uint8_t txHang)
m_loDev = on; m_loDev = on;
m_txHang = txHang * 1200U; m_txHang = txHang * 1200U;
} }
+33 -29
View File
@@ -22,36 +22,40 @@
/* /*
Pin definitions for DRCC_DVM BG7NQF board rev1 Pin definitions for DRCC_DVM BG7NQF board rev1
PTT PB12 output TX/PTT_LED PB12 output
LED_PTT PB4 output RX/COS_LED PB5 output
LED_COS PB5 output STATUS_LED PB10 output
LED_SRV PB10 output
COS PB13 input
DSTAR N/A COS_IN PB13 input
DMR N/A
YSF N/A
P25 N/A
NXDN N/A
POCSAG N/A
MDSTAR PB14 output DSTAR N/A
MDMR PB8 output DMR N/A
MYSF PB9 output YSF N/A
MP25 PB15 output P25 N/A
MNXDN N/A NXDN N/A
MPOCSAG N/A POCSAG N/A
RX PB0 analog input MDMR/BIT0 PB8 output
RSSI PB1 analog input MYSF/BIT1 PB9 output
TX PA4 analog output MDSTAR/BIT2 PB14 output
MP25/BIT3 PB15 output Generic Mode Pins
MNXDN N/A
MPOCSAG N/A
EXT_CLK PA15 input RX PA0 analog input
RSSI PA1 analog input
TX PA4 analog output
UART1_TX PA9 output EXT_CLK PA15 input
UART1_RX PA10 output
UART2_TX PA2 output UART1_TX PA9 output
UART2_RX PA3 output UART1_RX PA10 output Host Data Communication
UART2_TX PA2 output
UART2_RX PA3 output Nextion Data Communication
I2C1_SCL PB6 output
I2C1_SDA PB7 output OLED Data Communication as master
*/ */
@@ -124,13 +128,13 @@ UART2_RX PA3 output
#define PIN_RX GPIO_Pin_0 #define PIN_RX GPIO_Pin_0
#define PIN_RX_CH ADC_Channel_0 #define PIN_RX_CH ADC_Channel_0
#define PORT_RX GPIOB #define PORT_RX GPIOA
#define RCC_Per_RX RCC_AHB1Periph_GPIOB #define RCC_Per_RX RCC_AHB1Periph_GPIOA
#define PIN_RSSI GPIO_Pin_1 #define PIN_RSSI GPIO_Pin_1
#define PIN_RSSI_CH ADC_Channel_1 #define PIN_RSSI_CH ADC_Channel_1
#define PORT_RSSI GPIOB #define PORT_RSSI GPIOA
#define RCC_Per_RSSI RCC_AHB1Periph_GPIOB #define RCC_Per_RSSI RCC_AHB1Periph_GPIOA
#define PIN_TX GPIO_Pin_4 #define PIN_TX GPIO_Pin_4
#define PIN_TX_CH DAC_Channel_1 #define PIN_TX_CH DAC_Channel_1