mirror of
https://github.com/g4klx/MMDVM.git
synced 2026-10-15 16:24:11 +02:00
Compare commits
98
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
459a1413b7 | ||
|
|
2cf2ce4dfa | ||
|
|
5f29808b80 | ||
|
|
063b21f999 | ||
|
|
89b8641955 | ||
|
|
6397c720e8 | ||
|
|
50c1e5aa3f | ||
|
|
970d02773f | ||
|
|
ff9fb61467 | ||
|
|
ff375abb0e | ||
|
|
63e456919a | ||
|
|
7169836621 | ||
|
|
48034189d2 | ||
|
|
8e52bdcc5c | ||
|
|
66feb9d50b | ||
|
|
60d654865d | ||
|
|
435544f7a1 | ||
|
|
75e32e1b71 | ||
|
|
c54c13c146 | ||
|
|
4cba5931f4 | ||
|
|
d0062a55f8 | ||
|
|
66ea3ad0d1 | ||
|
|
85acdc7121 | ||
|
|
a2518e99f2 | ||
|
|
3bb7cde322 | ||
|
|
fa29a27695 | ||
|
|
e30eb3adaf | ||
|
|
9b0fed975c | ||
|
|
5ca9313db8 | ||
|
|
feff1ee2c7 | ||
|
|
77e0deee76 | ||
|
|
6769a6a0d7 | ||
|
|
c6485de10c | ||
|
|
cc018515e1 | ||
|
|
278622dd88 | ||
|
|
783822e401 | ||
|
|
45cdd8f799 | ||
|
|
85e33bc49f | ||
|
|
917dab755a | ||
|
|
1d75a360ea | ||
|
|
4593951680 | ||
|
|
10a043f641 | ||
|
|
2f05727b25 | ||
|
|
7519429c43 | ||
|
|
b0e2867663 | ||
|
|
cb25a64a4b | ||
|
|
2099096acb | ||
|
|
51b0be7e2e | ||
|
|
d30d768bdc | ||
|
|
7107625b12 | ||
|
|
554094540d | ||
|
|
ddaac983a4 | ||
|
|
4b3736a189 | ||
|
|
fd5822df19 | ||
|
|
508c3000fa | ||
|
|
fcd1012ff4 | ||
|
|
f2e9f2d753 | ||
|
|
96dc2282a8 | ||
|
|
00891dfa2f | ||
|
|
0bfc59b2d7 | ||
|
|
387221665f | ||
|
|
8da0ea7740 | ||
|
|
46035fa212 | ||
|
|
aa52b03bc2 | ||
|
|
cf849ccf65 | ||
|
|
83dd360062 | ||
|
|
551aa3bb20 | ||
|
|
cb78220156 | ||
|
|
22297c613c | ||
|
|
24741a11c6 | ||
|
|
293a5b6912 | ||
|
|
7e8d018242 | ||
|
|
3b84cf85c3 | ||
|
|
ef8f5bb80b | ||
|
|
037810b23b | ||
|
|
f7de632cd5 | ||
|
|
a554a86202 | ||
|
|
4eda2b61f5 | ||
|
|
f06bd5125b | ||
|
|
a0afe0e54f | ||
|
|
edbf2b3ec0 | ||
|
|
2833ed2d2e | ||
|
|
d91a155084 | ||
|
|
dc9d83f9f0 | ||
|
|
2a5690fd4d | ||
|
|
161736925e | ||
|
|
c43616f3c5 | ||
|
|
e6adc0a296 | ||
|
|
f195fd6f66 | ||
|
|
16a43db79a | ||
|
|
a033b2db7b | ||
|
|
88ab312da0 | ||
|
|
49383ca921 | ||
|
|
ed07175437 | ||
|
|
c8208ab1df | ||
|
|
90797696dd | ||
|
|
c22f360ed1 | ||
|
|
5d74c2f7bf |
+1
-1
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -40,4 +40,4 @@ private:
|
|||||||
uint8_t m_downSampleIndex;
|
uint8_t m_downSampleIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user