mirror of
https://github.com/g4klx/MMDVM.git
synced 2026-10-15 16:24:11 +02:00
Compare commits
15
Commits
I2C
...
M17_AX25_FM
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee07f76bd5 | ||
|
|
d063a1da1e | ||
|
|
6a4dad4c44 | ||
|
|
ed6bd66fab | ||
|
|
1a07a6f0d1 | ||
|
|
70bf47f93e | ||
|
|
a5eaafc7e0 | ||
|
|
2200945857 | ||
|
|
63a8e61a45 | ||
|
|
7275f65e44 | ||
|
|
2aabdb61ab | ||
|
|
96c0e5b141 | ||
|
|
9c883cfafd | ||
|
|
8a1ab88c3a | ||
|
|
f4e1c0b401 |
@@ -58,7 +58,7 @@
|
||||
// Frequencies such as 10.0 Mhz (48000 * 208.333) or 20 Mhz (48000 * 416.666) are not suitable.
|
||||
//
|
||||
// For 12 MHz
|
||||
// #define EXTERNAL_OSC 12000000
|
||||
#define EXTERNAL_OSC 12000000
|
||||
// For 12.288 MHz
|
||||
// #define EXTERNAL_OSC 12288000
|
||||
// For 14.4 MHz
|
||||
@@ -66,10 +66,10 @@
|
||||
// For 19.2 MHz
|
||||
// #define EXTERNAL_OSC 19200000
|
||||
|
||||
// Use a higher baudrate for host communication. Required for FM network !
|
||||
// #define SERIAL_SPEED 115200 //suitable for most older boards (Arduino, Due STM32F1_POG etc). External FM will NOT work with this !
|
||||
// #define SERIAL_SPEED 230400 // Only works on newer board M4, M7, Teensy. External FM might work with this
|
||||
#define SERIAL_SPEED 460800 // Only works on newer board M4, M7, Teensy. External FM should work with this
|
||||
// Select a baud rate for host communication. The faster speeds are needed for external FM to work.
|
||||
// #define SERIAL_SPEED 115200 // Suitable for most older boards (Arduino Due, STM32F1_POG, etc). External FM will NOT work with this!
|
||||
// #define SERIAL_SPEED 230400 // Only works on newer boards like fast M4, M7, Teensy 3.x. External FM might work with this
|
||||
#define SERIAL_SPEED 460800 // Only works on newer boards like fast M4, M7, Teensy 3.x. External FM should work with this
|
||||
|
||||
// Allow the use of the COS line to lockout the modem
|
||||
// #define USE_COS_AS_LOCKOUT
|
||||
@@ -129,5 +129,11 @@
|
||||
// Use the D-Star and YSF LEDs for FM
|
||||
#define USE_ALTERNATE_FM_LEDS
|
||||
|
||||
#if defined(STM32F1_POG)
|
||||
// Slower boards need to run their serial at 115200 baud
|
||||
#undef SERIAL_SPEED
|
||||
#define SERIAL_SPEED 115200
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -28,13 +28,6 @@ const uint16_t FM_SERIAL_BLOCK_SIZE = 80U;//this is the number of sample pairs t
|
||||
//three times this value shall never exceed 252
|
||||
const uint16_t FM_SERIAL_BLOCK_SIZE_BYTES = FM_SERIAL_BLOCK_SIZE * 3U;
|
||||
|
||||
/*
|
||||
* Access Mode values are:
|
||||
* 0 - Carrier access with COS
|
||||
* 1 - CTCSS only access without COS
|
||||
* 2 - CTCSS only access with COS
|
||||
* 3 - CTCSS only access with COS to start, then carrier access with COS
|
||||
*/
|
||||
|
||||
CFM::CFM() :
|
||||
m_callsign(),
|
||||
@@ -63,6 +56,7 @@ m_filterStage2(32768, 0,-32768, 32768, -50339, 19052),
|
||||
m_filterStage3(32768, -65536, 32768, 32768, -64075, 31460),
|
||||
m_blanking(),
|
||||
m_accessMode(1U),
|
||||
m_linkMode(false),
|
||||
m_cosInvert(false),
|
||||
m_noiseSquelch(false),
|
||||
m_rfAudioBoost(1U),
|
||||
@@ -72,7 +66,9 @@ m_extEnabled(false),
|
||||
m_rxLevel(1),
|
||||
m_inputRFRB(2401U), // 100ms of audio + 1 sample
|
||||
m_outputRFRB(2400U), // 100ms of audio
|
||||
m_inputExtRB()
|
||||
m_inputExtRB(),
|
||||
m_rfSignal(false),
|
||||
m_extSignal(false)
|
||||
{
|
||||
m_statusTimer.setTimeout(1U, 0U);
|
||||
m_reverseTimer.setTimeout(0U, 150U);
|
||||
@@ -81,6 +77,14 @@ m_inputExtRB()
|
||||
}
|
||||
|
||||
void CFM::samples(bool cos, q15_t* samples, uint8_t length)
|
||||
{
|
||||
if (m_linkMode)
|
||||
linkSamples(cos, samples, length);
|
||||
else
|
||||
repeaterSamples(cos, samples, length);
|
||||
}
|
||||
|
||||
void CFM::repeaterSamples(bool cos, q15_t* samples, uint8_t length)
|
||||
{
|
||||
if (m_cosInvert)
|
||||
cos = !cos;
|
||||
@@ -219,6 +223,108 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length)
|
||||
}
|
||||
}
|
||||
|
||||
void CFM::linkSamples(bool cos, q15_t* samples, uint8_t length)
|
||||
{
|
||||
if (m_cosInvert)
|
||||
cos = !cos;
|
||||
|
||||
clock(length);
|
||||
|
||||
uint8_t i = 0U;
|
||||
for (; i < length; i++) {
|
||||
// ARMv7-M has hardware integer division
|
||||
q15_t currentRFSample = q15_t((q31_t(samples[i]) << 8) / m_rxLevel);
|
||||
|
||||
if (m_noiseSquelch)
|
||||
cos = m_squelch.process(currentRFSample);
|
||||
|
||||
q15_t currentExtSample;
|
||||
bool inputExt = m_inputExtRB.getSample(currentExtSample);//always consume the external input data so it does not overflow
|
||||
inputExt = inputExt && m_extEnabled;
|
||||
|
||||
switch (m_accessMode) {
|
||||
case 0U:
|
||||
if (!inputExt && !cos && m_modemState != STATE_FM)
|
||||
continue;
|
||||
else
|
||||
stateMachine(cos, inputExt);
|
||||
break;
|
||||
|
||||
case 1U: {
|
||||
bool ctcss = m_ctcssRX.process(currentRFSample);
|
||||
|
||||
// Delay the audio by 100ms to better match the CTCSS detector output
|
||||
m_inputRFRB.put(currentRFSample);
|
||||
m_inputRFRB.get(currentRFSample);
|
||||
|
||||
if (!inputExt && !ctcss && m_modemState != STATE_FM) {
|
||||
// No CTCSS detected, just carry on
|
||||
continue;
|
||||
} else if ((inputExt || ctcss) && m_modemState != STATE_FM) {
|
||||
// We had CTCSS or external input
|
||||
stateMachine(ctcss, inputExt);
|
||||
if (m_state == FS_LISTENING)
|
||||
continue;
|
||||
} else {
|
||||
stateMachine(ctcss, inputExt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2U: {
|
||||
bool ctcss = m_ctcssRX.process(currentRFSample);
|
||||
if (!inputExt && !ctcss && m_modemState != STATE_FM) {
|
||||
// No CTCSS detected, just carry on
|
||||
continue;
|
||||
} else if ((inputExt || (ctcss && cos)) && m_modemState != STATE_FM) {
|
||||
// We had CTCSS or external input
|
||||
stateMachine(ctcss && cos, inputExt);
|
||||
if (m_state == FS_LISTENING)
|
||||
continue;
|
||||
} else {
|
||||
stateMachine(ctcss && cos, inputExt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
bool ctcss = m_ctcssRX.process(currentRFSample);
|
||||
if (!inputExt && !ctcss && m_modemState != STATE_FM) {
|
||||
// No CTCSS detected, just carry on
|
||||
continue;
|
||||
} else if ((inputExt || (ctcss && cos)) && m_modemState != STATE_FM) {
|
||||
// We had CTCSS or external input
|
||||
stateMachine(ctcss && cos, inputExt);
|
||||
if (m_state == FS_LISTENING)
|
||||
continue;
|
||||
} else {
|
||||
stateMachine(cos, inputExt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_modemState != STATE_FM)
|
||||
continue;
|
||||
|
||||
if (m_rfSignal && m_extEnabled) {
|
||||
q15_t currentSample = m_blanking.process(currentRFSample);
|
||||
m_downSampler.addSample(currentSample);
|
||||
}
|
||||
|
||||
if (!m_extSignal)
|
||||
continue;
|
||||
|
||||
q15_t currentSample = currentExtSample * m_extAudioBoost;
|
||||
|
||||
currentSample = m_filterStage3.filter(m_filterStage2.filter(m_filterStage1.filter(currentSample)));
|
||||
|
||||
currentSample += m_ctcssTX.getAudio(m_reverseTimer.isRunning());
|
||||
|
||||
m_outputRFRB.put(currentSample);
|
||||
}
|
||||
}
|
||||
|
||||
void CFM::process()
|
||||
{
|
||||
uint16_t space = io.getSpace();
|
||||
@@ -287,6 +393,8 @@ void CFM::reset()
|
||||
m_squelch.reset();
|
||||
|
||||
m_needReverse = false;
|
||||
m_rfSignal = false;
|
||||
m_extSignal = false;
|
||||
}
|
||||
|
||||
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)
|
||||
@@ -317,9 +425,10 @@ uint8_t CFM::setAck(const char* rfAck, uint8_t speed, uint16_t frequency, uint8_
|
||||
return m_rfAck.setParams(rfAck, speed, frequency, level, level);
|
||||
}
|
||||
|
||||
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, uint8_t accessMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, 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, uint8_t accessMode, bool linkMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel)
|
||||
{
|
||||
m_accessMode = accessMode;
|
||||
m_linkMode = linkMode;
|
||||
m_cosInvert = cosInvert;
|
||||
m_noiseSquelch = noiseSquelch;
|
||||
|
||||
@@ -356,10 +465,14 @@ uint8_t CFM::setExt(const char* ack, uint8_t audioBoost, uint8_t speed, uint16_t
|
||||
|
||||
void CFM::stateMachine(bool validRFSignal, bool validExtSignal)
|
||||
{
|
||||
if (m_duplex)
|
||||
duplexStateMachine(validRFSignal, validExtSignal);
|
||||
else
|
||||
simplexStateMachine(validRFSignal, validExtSignal);
|
||||
if (m_linkMode) {
|
||||
linkStateMachine(validRFSignal, validExtSignal);
|
||||
} else {
|
||||
if (m_duplex)
|
||||
duplexStateMachine(validRFSignal, validExtSignal);
|
||||
else
|
||||
simplexStateMachine(validRFSignal, validExtSignal);
|
||||
}
|
||||
}
|
||||
|
||||
void CFM::simplexStateMachine(bool validRFSignal, bool validExtSignal)
|
||||
@@ -1009,6 +1122,63 @@ void CFM::timeoutExtWaitStateSimplex(bool validSignal)
|
||||
}
|
||||
}
|
||||
|
||||
void CFM::linkStateMachine(bool validRFSignal, bool validExtSignal)
|
||||
{
|
||||
if (validRFSignal && !m_rfSignal) {
|
||||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
|
||||
if (!m_extSignal) {
|
||||
DEBUG1("State to RELAYING_RF");
|
||||
m_state = FS_RELAYING_RF;
|
||||
m_statusTimer.start();
|
||||
serial.writeFMStatus(m_state);
|
||||
}
|
||||
|
||||
m_rfSignal = true;
|
||||
}
|
||||
|
||||
if (validExtSignal && !m_extSignal) {
|
||||
if (!m_rfSignal) {
|
||||
DEBUG1("State to RELAYING_EXT");
|
||||
m_state = FS_RELAYING_EXT;
|
||||
m_statusTimer.start();
|
||||
serial.writeFMStatus(m_state);
|
||||
}
|
||||
|
||||
insertSilence(50U);
|
||||
|
||||
m_extSignal = true;
|
||||
}
|
||||
|
||||
if (!validRFSignal && m_rfSignal) {
|
||||
io.setDecode(false);
|
||||
io.setADCDetection(false);
|
||||
|
||||
if (!m_extSignal) {
|
||||
DEBUG1("State to LISTENING");
|
||||
m_state = FS_LISTENING;
|
||||
m_statusTimer.stop();
|
||||
}
|
||||
|
||||
m_rfSignal = false;
|
||||
|
||||
if (m_extEnabled)
|
||||
serial.writeFMEOT();
|
||||
}
|
||||
|
||||
if (!validExtSignal && m_extSignal) {
|
||||
if (!m_rfSignal) {
|
||||
DEBUG1("State to LISTENING");
|
||||
m_state = FS_LISTENING;
|
||||
m_statusTimer.stop();
|
||||
}
|
||||
|
||||
m_needReverse = true;
|
||||
m_extSignal = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CFM::sendCallsign()
|
||||
{
|
||||
if (m_holdoffTimer.isRunning()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020,2021 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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
|
||||
@@ -63,7 +63,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 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 ctcssHighThreshold, uint8_t ctcssLowThreshold, uint8_t ctcssLevel, uint8_t kerchunkTime, uint8_t hangTime, uint8_t accessMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, 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, uint8_t accessMode, bool linkMode, bool cosInvert, bool noiseSquelch, uint8_t squelchHighThreshold, uint8_t squelchLowThreshold, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
|
||||
uint8_t setExt(const char* ack, uint8_t audioBoost, uint8_t speed, uint16_t frequency, uint8_t level);
|
||||
|
||||
uint8_t getSpace() const;
|
||||
@@ -97,6 +97,7 @@ private:
|
||||
CFMDirectFormI m_filterStage3;
|
||||
CFMBlanking m_blanking;
|
||||
uint8_t m_accessMode;
|
||||
bool m_linkMode;
|
||||
bool m_cosInvert;
|
||||
bool m_noiseSquelch;
|
||||
q15_t m_rfAudioBoost;
|
||||
@@ -107,9 +108,14 @@ private:
|
||||
CRingBuffer<q15_t> m_inputRFRB;
|
||||
CRingBuffer<q15_t> m_outputRFRB;
|
||||
CFMUpSampler m_inputExtRB;
|
||||
bool m_rfSignal;
|
||||
bool m_extSignal;
|
||||
|
||||
void stateMachine(bool validRFSignal, bool validExtSignal);
|
||||
|
||||
void repeaterSamples(bool cos, q15_t* samples, uint8_t length);
|
||||
void linkSamples(bool cos, q15_t* samples, uint8_t length);
|
||||
|
||||
void duplexStateMachine(bool validRFSignal, bool validExtSignal);
|
||||
void listeningStateDuplex(bool validRFSignal, bool validExtSignal);
|
||||
void kerchunkRFStateDuplex(bool validSignal);
|
||||
@@ -135,6 +141,8 @@ private:
|
||||
void timeoutExtStateSimplex(bool validSignal);
|
||||
void timeoutExtWaitStateSimplex(bool validSignal);
|
||||
|
||||
void linkStateMachine(bool validRFSignal, bool validExtSignal);
|
||||
|
||||
void clock(uint8_t length);
|
||||
|
||||
void sendCallsign();
|
||||
|
||||
@@ -746,6 +746,7 @@ void CIO::setMode(MMDVM_STATE state)
|
||||
case STATE_M17: setM17Int(false); break;
|
||||
case STATE_POCSAG: setPOCSAGInt(false); break;
|
||||
case STATE_FM: setFMInt(false); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
@@ -757,6 +758,7 @@ void CIO::setMode(MMDVM_STATE state)
|
||||
case STATE_M17: setM17Int(true); break;
|
||||
case STATE_POCSAG: setPOCSAGInt(true); break;
|
||||
case STATE_FM: setFMInt(true); break;
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+9
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* 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
|
||||
@@ -27,18 +27,17 @@ const unsigned int M17_FRAME_LENGTH_SYMBOLS = M17_FRAME_LENGTH_BITS / 2U;
|
||||
const unsigned int M17_FRAME_LENGTH_SAMPLES = M17_FRAME_LENGTH_SYMBOLS * M17_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const unsigned int M17_SYNC_LENGTH_BITS = 16U;
|
||||
const unsigned int M17_SYNC_LENGTH_BYTES = M17_SYNC_LENGTH_BITS / 8U;
|
||||
const unsigned int M17_SYNC_LENGTH_SYMBOLS = M17_SYNC_LENGTH_BITS / 2U;
|
||||
const unsigned int M17_SYNC_LENGTH_SAMPLES = M17_SYNC_LENGTH_SYMBOLS * M17_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const uint8_t M17_LINK_SETUP_SYNC_BYTES[] = {0x55U, 0xF7U};
|
||||
const uint8_t M17_STREAM_SYNC_BYTES[] = {0xFFU, 0x5DU};
|
||||
const uint8_t M17_PACKET_SYNC_BYTES[] = {0x75U, 0xFFU};
|
||||
|
||||
const uint8_t M17_SYNC_BYTES_LENGTH = 2U;
|
||||
const uint8_t M17_EOF_SYNC_BYTES[] = {0x55U, 0x5DU};
|
||||
|
||||
const uint16_t M17_LINK_SETUP_SYNC_BITS = 0x55F7U;
|
||||
const uint16_t M17_STREAM_SYNC_BITS = 0xFF5DU;
|
||||
const uint16_t M17_PACKET_SYNC_BITS = 0x75FFU;
|
||||
const uint16_t M17_EOF_SYNC_BITS = 0x555DU;
|
||||
|
||||
// 5 5 F 7
|
||||
// 01 01 01 01 11 11 01 11
|
||||
@@ -56,13 +55,13 @@ const int8_t M17_STREAM_SYNC_SYMBOLS_VALUES[] = {-3, -3, -3, -3, +3, +3, -3, +3}
|
||||
|
||||
const uint8_t M17_STREAM_SYNC_SYMBOLS = 0x0DU;
|
||||
|
||||
// 7 5 F F
|
||||
// 01 11 01 01 11 11 11 11
|
||||
// +3 -3 +3 +3 -3 -3 -3 -3
|
||||
// 5 5 5 D
|
||||
// 01 01 01 01 01 01 11 01
|
||||
// +3 +3 +3 +3 +3 +3 -3 +3
|
||||
|
||||
const int8_t M17_PACKET_SYNC_SYMBOLS_VALUES[] = {+3, -3, +3, +3, -3, -3, -3, -3};
|
||||
const int8_t M17_EOF_SYNC_SYMBOLS_VALUES[] = {+3, +3, +3, +3, +3, +3, -3, +3};
|
||||
|
||||
const uint8_t M17_PACKET_SYNC_SYMBOLS = 0xB0U;
|
||||
const uint8_t M17_EOF_SYNC_SYMBOLS = 0xFDU;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -105,7 +105,6 @@ void CM17RX::samples(const q15_t* samples, uint16_t* rssi, uint8_t length)
|
||||
switch (m_state) {
|
||||
case M17RXS_LINK_SETUP:
|
||||
case M17RXS_STREAM:
|
||||
case M17RXS_PACKET:
|
||||
processData(sample);
|
||||
break;
|
||||
default:
|
||||
@@ -127,9 +126,8 @@ void CM17RX::processNone(q15_t sample)
|
||||
{
|
||||
bool ret1 = correlateSync(M17_LINK_SETUP_SYNC_SYMBOLS, M17_LINK_SETUP_SYNC_SYMBOLS_VALUES, M17_LINK_SETUP_SYNC_BYTES, MAX_SYNC_SYMBOL_START_ERRS, MAX_SYNC_BIT_START_ERRS);
|
||||
bool ret2 = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_START_ERRS, MAX_SYNC_BIT_START_ERRS);
|
||||
// bool ret3 = correlateSync(M17_PACKET_SYNC_SYMBOLS, M17_PACKET_SYNC_SYMBOLS_VALUES, M17_PACKET_SYNC_BYTES, MAX_SYNC_SYMBOL_START_ERRS, MAX_SYNC_BIT_START_ERRS);
|
||||
|
||||
if (ret1 || ret2 /* || ret3 */ ) {
|
||||
if (ret1 || ret2) {
|
||||
// On the first sync, start the countdown to the state change
|
||||
if (m_countdown == 0U) {
|
||||
m_rssiAccum = 0U;
|
||||
@@ -144,7 +142,6 @@ void CM17RX::processNone(q15_t sample)
|
||||
|
||||
if (ret1) m_nextState = M17RXS_LINK_SETUP;
|
||||
if (ret2) m_nextState = M17RXS_STREAM;
|
||||
// if (ret3) m_nextState = M17RXS_PACKET;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,28 +165,42 @@ void CM17RX::processNone(q15_t sample)
|
||||
|
||||
void CM17RX::processData(q15_t sample)
|
||||
{
|
||||
bool eof = false;
|
||||
|
||||
if (m_minSyncPtr < m_maxSyncPtr) {
|
||||
if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr) {
|
||||
bool ret1 = correlateSync(M17_LINK_SETUP_SYNC_SYMBOLS, M17_LINK_SETUP_SYNC_SYMBOLS_VALUES, M17_LINK_SETUP_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
bool ret2 = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
// bool ret3 = correlateSync(M17_PACKET_SYNC_SYMBOLS, M17_PACKET_SYNC_SYMBOLS_VALUES, M17_PACKET_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
bool ret = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
|
||||
if (ret1) m_state = M17RXS_LINK_SETUP;
|
||||
if (ret2) m_state = M17RXS_STREAM;
|
||||
// if (ret3) m_state = M17RXS_PACKET;
|
||||
eof = correlateSync(M17_EOF_SYNC_SYMBOLS, M17_EOF_SYNC_SYMBOLS_VALUES, M17_EOF_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
|
||||
if (ret) m_state = M17RXS_STREAM;
|
||||
}
|
||||
} else {
|
||||
if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr) {
|
||||
bool ret1 = correlateSync(M17_LINK_SETUP_SYNC_SYMBOLS, M17_LINK_SETUP_SYNC_SYMBOLS_VALUES, M17_LINK_SETUP_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
bool ret2 = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
// bool ret3 = correlateSync(M17_PACKET_SYNC_SYMBOLS, M17_PACKET_SYNC_SYMBOLS_VALUES, M17_PACKET_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
bool ret = correlateSync(M17_STREAM_SYNC_SYMBOLS, M17_STREAM_SYNC_SYMBOLS_VALUES, M17_STREAM_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
|
||||
if (ret1) m_state = M17RXS_LINK_SETUP;
|
||||
if (ret2) m_state = M17RXS_STREAM;
|
||||
// if (ret3) m_state = M17RXS_PACKET;
|
||||
eof = correlateSync(M17_EOF_SYNC_SYMBOLS, M17_EOF_SYNC_SYMBOLS_VALUES, M17_EOF_SYNC_BYTES, MAX_SYNC_SYMBOL_RUN_ERRS, MAX_SYNC_BIT_RUN_ERRS);
|
||||
|
||||
if (ret) m_state = M17RXS_STREAM;
|
||||
}
|
||||
}
|
||||
|
||||
if (eof) {
|
||||
DEBUG4("M17RX: eof sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
|
||||
|
||||
io.setDecode(false);
|
||||
io.setADCDetection(false);
|
||||
|
||||
serial.writeM17EOT();
|
||||
|
||||
m_state = M17RXS_NONE;
|
||||
m_endPtr = NOENDPTR;
|
||||
m_averagePtr = NOAVEPTR;
|
||||
m_countdown = 0U;
|
||||
m_nextState = M17RXS_NONE;
|
||||
m_maxCorr = 0;
|
||||
}
|
||||
|
||||
if (m_dataPtr == m_endPtr) {
|
||||
// Only update the centre and threshold if they are from a good sync
|
||||
if (m_lostCount == MAX_SYNC_FRAMES) {
|
||||
@@ -211,9 +222,8 @@ void CM17RX::processData(q15_t sample)
|
||||
case M17RXS_STREAM:
|
||||
DEBUG4("M17RX: stream sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
|
||||
break;
|
||||
case M17RXS_PACKET:
|
||||
DEBUG4("M17RX: packet sync found pos/centre/threshold", m_syncPtr, m_centreVal, m_thresholdVal);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t frame[M17_FRAME_LENGTH_BYTES + 3U];
|
||||
@@ -236,8 +246,7 @@ void CM17RX::processData(q15_t sample)
|
||||
m_nextState = M17RXS_NONE;
|
||||
m_maxCorr = 0;
|
||||
} else {
|
||||
frame[0U] = 0x00U;
|
||||
frame[0U] |= m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U;
|
||||
frame[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U;
|
||||
|
||||
switch (m_state) {
|
||||
case M17RXS_LINK_SETUP:
|
||||
@@ -246,9 +255,8 @@ void CM17RX::processData(q15_t sample)
|
||||
case M17RXS_STREAM:
|
||||
writeRSSIStream(frame);
|
||||
break;
|
||||
case M17RXS_PACKET:
|
||||
writeRSSIPacket(frame);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_maxCorr = 0;
|
||||
@@ -308,11 +316,11 @@ bool CM17RX::correlateSync(uint8_t syncSymbols, const int8_t* syncSymbolValues,
|
||||
if (startPtr >= M17_FRAME_LENGTH_SAMPLES)
|
||||
startPtr -= M17_FRAME_LENGTH_SAMPLES;
|
||||
|
||||
uint8_t sync[M17_SYNC_BYTES_LENGTH];
|
||||
uint8_t sync[M17_SYNC_LENGTH_BYTES];
|
||||
samplesToBits(startPtr, M17_SYNC_LENGTH_SYMBOLS, sync, 0U, m_centreVal, m_thresholdVal);
|
||||
|
||||
uint8_t errs = 0U;
|
||||
for (uint8_t i = 0U; i < M17_SYNC_BYTES_LENGTH; i++)
|
||||
for (uint8_t i = 0U; i < M17_SYNC_LENGTH_BYTES; i++)
|
||||
errs += countBits8(sync[i] ^ syncBytes[i]);
|
||||
|
||||
if (errs <= maxBitErrs) {
|
||||
@@ -437,8 +445,8 @@ void CM17RX::writeRSSILinkSetup(uint8_t* data)
|
||||
if (m_rssiCount > 0U) {
|
||||
uint16_t rssi = m_rssiAccum / m_rssiCount;
|
||||
|
||||
data[121U] = (rssi >> 8) & 0xFFU;
|
||||
data[122U] = (rssi >> 0) & 0xFFU;
|
||||
data[49U] = (rssi >> 8) & 0xFFU;
|
||||
data[50U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeM17LinkSetup(data, M17_FRAME_LENGTH_BYTES + 3U);
|
||||
} else {
|
||||
@@ -458,8 +466,8 @@ void CM17RX::writeRSSIStream(uint8_t* data)
|
||||
if (m_rssiCount > 0U) {
|
||||
uint16_t rssi = m_rssiAccum / m_rssiCount;
|
||||
|
||||
data[121U] = (rssi >> 8) & 0xFFU;
|
||||
data[122U] = (rssi >> 0) & 0xFFU;
|
||||
data[49U] = (rssi >> 8) & 0xFFU;
|
||||
data[50U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeM17Stream(data, M17_FRAME_LENGTH_BYTES + 3U);
|
||||
} else {
|
||||
@@ -473,26 +481,5 @@ void CM17RX::writeRSSIStream(uint8_t* data)
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
void CM17RX::writeRSSIPacket(uint8_t* data)
|
||||
{
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
if (m_rssiCount > 0U) {
|
||||
uint16_t rssi = m_rssiAccum / m_rssiCount;
|
||||
|
||||
data[121U] = (rssi >> 8) & 0xFFU;
|
||||
data[122U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeM17Packet(data, M17_FRAME_LENGTH_BYTES + 3U);
|
||||
} else {
|
||||
serial.writeM17Packet(data, M17_FRAME_LENGTH_BYTES + 1U);
|
||||
}
|
||||
#else
|
||||
serial.writeM17Packet(data, M17_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
|
||||
m_rssiAccum = 0U;
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
enum M17RX_STATE {
|
||||
M17RXS_NONE,
|
||||
M17RXS_LINK_SETUP,
|
||||
M17RXS_STREAM,
|
||||
M17RXS_PACKET
|
||||
M17RXS_STREAM
|
||||
};
|
||||
|
||||
class CM17RX {
|
||||
@@ -70,7 +69,6 @@ private:
|
||||
void samplesToBits(uint16_t start, uint16_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold);
|
||||
void writeRSSILinkSetup(uint8_t* data);
|
||||
void writeRSSIStream(uint8_t* data);
|
||||
void writeRSSIPacket(uint8_t* data);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2017 by Andy Uribe CA6JAU
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -33,10 +33,10 @@ static q15_t RRC_0_5_FILTER[] = {0, 0, 0, 0, -290, -174, 142, 432, 438, 90, -387
|
||||
438, 432, 142, -174, -290}; // numTaps = 45, L = 5
|
||||
const uint16_t RRC_0_5_FILTER_PHASE_LEN = 9U; // phaseLength = numTaps/L
|
||||
|
||||
const q15_t M17_LEVELA = 1683;
|
||||
const q15_t M17_LEVELB = 561;
|
||||
const q15_t M17_LEVELC = -561;
|
||||
const q15_t M17_LEVELD = -1683;
|
||||
const q15_t M17_LEVELA = 1481;
|
||||
const q15_t M17_LEVELB = 494;
|
||||
const q15_t M17_LEVELC = -494;
|
||||
const q15_t M17_LEVELD = -1481;
|
||||
|
||||
const uint8_t M17_START_SYNC = 0x77U;
|
||||
const uint8_t M17_END_SYNC = 0xFFU;
|
||||
|
||||
+83
-56
@@ -67,6 +67,7 @@ const uint8_t MMDVM_M17_LINK_SETUP = 0x45U;
|
||||
const uint8_t MMDVM_M17_STREAM = 0x46U;
|
||||
const uint8_t MMDVM_M17_PACKET = 0x47U;
|
||||
const uint8_t MMDVM_M17_LOST = 0x48U;
|
||||
const uint8_t MMDVM_M17_EOT = 0x49U;
|
||||
|
||||
const uint8_t MMDVM_POCSAG_DATA = 0x50U;
|
||||
|
||||
@@ -146,26 +147,26 @@ m_i2CData()
|
||||
{
|
||||
}
|
||||
|
||||
void CSerialPort::sendACK()
|
||||
void CSerialPort::sendACK(uint8_t type)
|
||||
{
|
||||
uint8_t reply[4U];
|
||||
|
||||
reply[0U] = MMDVM_FRAME_START;
|
||||
reply[1U] = 4U;
|
||||
reply[2U] = MMDVM_ACK;
|
||||
reply[3U] = m_buffer[2U];
|
||||
reply[3U] = type;
|
||||
|
||||
writeInt(1U, reply, 4);
|
||||
}
|
||||
|
||||
void CSerialPort::sendNAK(uint8_t err)
|
||||
void CSerialPort::sendNAK(uint8_t type, uint8_t err)
|
||||
{
|
||||
uint8_t reply[5U];
|
||||
|
||||
reply[0U] = MMDVM_FRAME_START;
|
||||
reply[1U] = 5U;
|
||||
reply[2U] = MMDVM_NAK;
|
||||
reply[3U] = m_buffer[2U];
|
||||
reply[3U] = type;
|
||||
reply[4U] = err;
|
||||
|
||||
writeInt(1U, reply, 5);
|
||||
@@ -374,22 +375,41 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length)
|
||||
bool rxInvert = (data[0U] & 0x01U) == 0x01U;
|
||||
bool txInvert = (data[0U] & 0x02U) == 0x02U;
|
||||
bool pttInvert = (data[0U] & 0x04U) == 0x04U;
|
||||
#if defined(MODE_YSF)
|
||||
bool ysfLoDev = (data[0U] & 0x08U) == 0x08U;
|
||||
#endif
|
||||
bool useCOSAsLockout = (data[0U] & 0x20U) == 0x20U;
|
||||
bool simplex = (data[0U] & 0x80U) == 0x80U;
|
||||
|
||||
m_debug = (data[0U] & 0x10U) == 0x10U;
|
||||
|
||||
#if defined(MODE_DSTAR)
|
||||
bool dstarEnable = (data[1U] & 0x01U) == 0x01U;
|
||||
#endif
|
||||
#if defined(MODE_DMR)
|
||||
bool dmrEnable = (data[1U] & 0x02U) == 0x02U;
|
||||
#endif
|
||||
#if defined(MODE_YSF)
|
||||
bool ysfEnable = (data[1U] & 0x04U) == 0x04U;
|
||||
#endif
|
||||
#if defined(MODE_P25)
|
||||
bool p25Enable = (data[1U] & 0x08U) == 0x08U;
|
||||
#endif
|
||||
#if defined(MODE_NXDN)
|
||||
bool nxdnEnable = (data[1U] & 0x10U) == 0x10U;
|
||||
#endif
|
||||
#if defined(MODE_FM)
|
||||
bool fmEnable = (data[1U] & 0x20U) == 0x20U;
|
||||
#endif
|
||||
#if defined(MODE_M17)
|
||||
bool m17Enable = (data[1U] & 0x40U) == 0x40U;
|
||||
|
||||
#endif
|
||||
#if defined(MODE_POCSAG)
|
||||
bool pocsagEnable = (data[2U] & 0x01U) == 0x01U;
|
||||
#endif
|
||||
#if defined(MODE_AX25)
|
||||
bool ax25Enable = (data[2U] & 0x02U) == 0x02U;
|
||||
#endif
|
||||
|
||||
uint8_t txDelay = data[3U];
|
||||
if (txDelay > 50U)
|
||||
@@ -480,17 +500,28 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length)
|
||||
uint8_t fmTXLevel = data[16U];
|
||||
uint8_t ax25TXLevel = data[17U];
|
||||
|
||||
#if defined(MODE_YSF)
|
||||
uint8_t ysfTXHang = data[20U];
|
||||
#endif
|
||||
#if defined(MODE_P25)
|
||||
uint8_t p25TXHang = data[21U];
|
||||
#endif
|
||||
#if defined(MODE_NXDN)
|
||||
uint8_t nxdnTXHang = data[22U];
|
||||
#endif
|
||||
#if defined(MODE_M17)
|
||||
uint8_t m17TXHang = data[23U];
|
||||
#endif
|
||||
|
||||
#if defined(MODE_DMR)
|
||||
uint8_t colorCode = data[26U];
|
||||
if (colorCode > 15U)
|
||||
return 4U;
|
||||
|
||||
uint8_t dmrDelay = data[27U];
|
||||
#endif
|
||||
|
||||
#if defined(MODE_AX25)
|
||||
int8_t ax25RXTwist = int8_t(data[28U]) - 128;
|
||||
if (ax25RXTwist < -4 || ax25RXTwist > 10)
|
||||
return 4U;
|
||||
@@ -498,6 +529,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint16_t length)
|
||||
uint8_t ax25TXDelay = data[29U];
|
||||
uint8_t ax25SlotTime = data[30U];
|
||||
uint8_t ax25PPersist = data[31U];
|
||||
#endif
|
||||
|
||||
setMode(modemState);
|
||||
|
||||
@@ -620,6 +652,7 @@ uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint16_t length)
|
||||
uint8_t hangTime = data[7U];
|
||||
|
||||
uint8_t accessMode = data[8U] & 0x0FU;
|
||||
bool linkMode = (data[8U] & 0x20U) == 0x20U;
|
||||
bool noiseSquelch = (data[8U] & 0x40U) == 0x40U;
|
||||
bool cosInvert = (data[8U] & 0x80U) == 0x80U;
|
||||
|
||||
@@ -630,7 +663,7 @@ uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint16_t length)
|
||||
uint8_t squelchHighThreshold = data[12U];
|
||||
uint8_t squelchLowThreshold = data[13U];
|
||||
|
||||
return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, hangTime, accessMode, cosInvert, noiseSquelch, squelchHighThreshold, squelchLowThreshold, rfAudioBoost, maxDev, rxLevel);
|
||||
return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, hangTime, accessMode, linkMode, cosInvert, noiseSquelch, squelchHighThreshold, squelchLowThreshold, rfAudioBoost, maxDev, rxLevel);
|
||||
}
|
||||
|
||||
uint8_t CSerialPort::setFMParams4(const uint8_t* data, uint16_t length)
|
||||
@@ -939,7 +972,7 @@ void CSerialPort::process()
|
||||
}
|
||||
writeSerialData(buffer, serialAvail - m_lastSerialAvail);
|
||||
m_lastSerialAvailCount = 0U;
|
||||
} else if (serialAvail > 0U && serialAvail == m_lastSerialAvail) {
|
||||
} else if (serialAvail > 0 && serialAvail == m_lastSerialAvail) {
|
||||
m_lastSerialAvailCount++;
|
||||
} else {
|
||||
m_lastSerialAvail = serialAvail;
|
||||
@@ -980,61 +1013,61 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
case MMDVM_SET_CONFIG:
|
||||
err = setConfig(buffer, length);
|
||||
if (err == 0U)
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
else
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
break;
|
||||
|
||||
case MMDVM_SET_MODE:
|
||||
err = setMode(buffer, length);
|
||||
if (err == 0U)
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
else
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
break;
|
||||
|
||||
case MMDVM_SET_FREQ:
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
break;
|
||||
|
||||
#if defined(MODE_FM)
|
||||
case MMDVM_FM_PARAMS1:
|
||||
err = setFMParams1(buffer, length);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 1", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_PARAMS2:
|
||||
err = setFMParams2(buffer, length);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 2", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_PARAMS3:
|
||||
err = setFMParams3(buffer, length);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 3", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_PARAMS4:
|
||||
err = setFMParams4(buffer, length);
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
} else {
|
||||
DEBUG2("Received invalid FM params 4", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
@@ -1042,7 +1075,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
case MMDVM_FM_PARAMS2:
|
||||
case MMDVM_FM_PARAMS3:
|
||||
case MMDVM_FM_PARAMS4:
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -1072,10 +1105,10 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
err = calPOCSAG.write(buffer, length);
|
||||
#endif
|
||||
if (err == 0U) {
|
||||
sendACK();
|
||||
sendACK(type);
|
||||
} else {
|
||||
DEBUG2("Received invalid calibration data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1085,7 +1118,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
err = cwIdTX.write(buffer, length);
|
||||
if (err != 0U) {
|
||||
DEBUG2("Invalid CW Id data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1100,7 +1133,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_DSTAR);
|
||||
} else {
|
||||
DEBUG2("Received invalid D-Star header", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1114,7 +1147,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_DSTAR);
|
||||
} else {
|
||||
DEBUG2("Received invalid D-Star data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1128,7 +1161,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_DSTAR);
|
||||
} else {
|
||||
DEBUG2("Received invalid D-Star EOT", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1146,7 +1179,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_DMR);
|
||||
} else {
|
||||
DEBUG2("Received invalid DMR data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1164,7 +1197,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_DMR);
|
||||
} else {
|
||||
DEBUG2("Received invalid DMR data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1185,7 +1218,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
}
|
||||
if (err != 0U) {
|
||||
DEBUG2("Received invalid DMR start", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1194,7 +1227,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
err = dmrTX.writeShortLC(buffer, length);
|
||||
if (err != 0U) {
|
||||
DEBUG2("Received invalid DMR Short LC", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1203,7 +1236,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
err = dmrTX.writeAbort(buffer, length);
|
||||
if (err != 0U) {
|
||||
DEBUG2("Received invalid DMR Abort", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1219,7 +1252,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_YSF);
|
||||
} else {
|
||||
DEBUG2("Received invalid System Fusion data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1235,7 +1268,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_P25);
|
||||
} else {
|
||||
DEBUG2("Received invalid P25 header", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1249,7 +1282,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_P25);
|
||||
} else {
|
||||
DEBUG2("Received invalid P25 LDU", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1265,7 +1298,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_NXDN);
|
||||
} else {
|
||||
DEBUG2("Received invalid NXDN data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1281,7 +1314,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_M17);
|
||||
} else {
|
||||
DEBUG2("Received invalid M17 link setup data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1295,11 +1328,11 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_M17);
|
||||
} else {
|
||||
DEBUG2("Received invalid M17 stream data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_M17_PACKET:
|
||||
case MMDVM_M17_EOT:
|
||||
if (m_m17Enable) {
|
||||
if (m_modemState == STATE_IDLE || m_modemState == STATE_M17)
|
||||
err = m17TX.writeData(buffer, length);
|
||||
@@ -1308,8 +1341,8 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
if (m_modemState == STATE_IDLE)
|
||||
setMode(STATE_M17);
|
||||
} else {
|
||||
DEBUG2("Received invalid M17 packet data", err);
|
||||
sendNAK(err);
|
||||
DEBUG2("Received invalid M17 EOT", err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1325,7 +1358,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_POCSAG);
|
||||
} else {
|
||||
DEBUG2("Received invalid POCSAG data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1341,7 +1374,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
setMode(STATE_FM);
|
||||
} else {
|
||||
DEBUG2("Received invalid FM data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1354,7 +1387,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
}
|
||||
if (err != 0U) {
|
||||
DEBUG2("Received invalid AX.25 data", err);
|
||||
sendNAK(err);
|
||||
sendNAK(type, err);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@@ -1382,7 +1415,7 @@ void CSerialPort::processMessage(uint8_t type, const uint8_t* buffer, uint16_t l
|
||||
|
||||
default:
|
||||
// Handle this, send a NAK back
|
||||
sendNAK(1U);
|
||||
sendNAK(type, 1U);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1709,7 +1742,7 @@ void CSerialPort::writeM17Stream(const uint8_t* data, uint8_t length)
|
||||
writeInt(1U, reply, count);
|
||||
}
|
||||
|
||||
void CSerialPort::writeM17Packet(const uint8_t* data, uint8_t length)
|
||||
void CSerialPort::writeM17EOT()
|
||||
{
|
||||
if (m_modemState != STATE_M17 && m_modemState != STATE_IDLE)
|
||||
return;
|
||||
@@ -1717,19 +1750,13 @@ void CSerialPort::writeM17Packet(const uint8_t* data, uint8_t length)
|
||||
if (!m_m17Enable)
|
||||
return;
|
||||
|
||||
uint8_t reply[130U];
|
||||
uint8_t reply[3U];
|
||||
|
||||
reply[0U] = MMDVM_FRAME_START;
|
||||
reply[1U] = 0U;
|
||||
reply[2U] = MMDVM_M17_PACKET;
|
||||
reply[1U] = 3U;
|
||||
reply[2U] = MMDVM_M17_EOT;
|
||||
|
||||
uint8_t count = 3U;
|
||||
for (uint8_t i = 0U; i < length; i++, count++)
|
||||
reply[count] = data[i];
|
||||
|
||||
reply[1U] = count;
|
||||
|
||||
writeInt(1U, reply, count);
|
||||
writeInt(1U, reply, 3);
|
||||
}
|
||||
|
||||
void CSerialPort::writeM17Lost()
|
||||
|
||||
+3
-3
@@ -67,8 +67,8 @@ public:
|
||||
#if defined(MODE_M17)
|
||||
void writeM17LinkSetup(const uint8_t* data, uint8_t length);
|
||||
void writeM17Stream(const uint8_t* data, uint8_t length);
|
||||
void writeM17Packet(const uint8_t* data, uint8_t length);
|
||||
void writeM17Lost();
|
||||
void writeM17EOT();
|
||||
#endif
|
||||
|
||||
#if defined(MODE_AX25)
|
||||
@@ -109,8 +109,8 @@ private:
|
||||
uint16_t m_lastSerialAvailCount;
|
||||
CRingBuffer<uint8_t> m_i2CData;
|
||||
|
||||
void sendACK();
|
||||
void sendNAK(uint8_t err);
|
||||
void sendACK(uint8_t type);
|
||||
void sendNAK(uint8_t type, uint8_t err);
|
||||
void getStatus();
|
||||
void getVersion();
|
||||
uint8_t setConfig(const uint8_t* data, uint16_t length);
|
||||
|
||||
Reference in New Issue
Block a user