mirror of
https://github.com/g4klx/MMDVM.git
synced 2026-10-16 16:54:12 +02:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b971c5bc38 | ||
|
|
598d32287d | ||
|
|
53d8cfa360 | ||
|
|
7fabddd7f1 |
+1
-1
@@ -24,7 +24,7 @@
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
const uint32_t PLLMAX = 0x10000U;
|
||||
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
const uint32_t PLLINC = PLLMAX / DSTAR_RADIO_BIT_LENGTH;
|
||||
const uint32_t INC = PLLINC / 32U;
|
||||
|
||||
// D-Star bit order version of 0x55 0x2D 0x16
|
||||
|
||||
+17
-37
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2009-2015,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2015 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
|
||||
@@ -19,50 +19,30 @@
|
||||
#if !defined(DSTARDEFINES_H)
|
||||
#define DSTARDEFINES_H
|
||||
|
||||
const unsigned int DSTAR_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
|
||||
const unsigned int DSTAR_RADIO_BIT_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_SYMBOLS = 660U;
|
||||
const unsigned int DSTAR_FEC_SECTION_LENGTH_SAMPLES = DSTAR_FEC_SECTION_LENGTH_SYMBOLS * DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
const unsigned int DSTAR_FEC_SECTION_LENGTH_BYTES = 83U;
|
||||
const unsigned int DSTAR_FEC_SECTION_LENGTH_BITS = 660U;
|
||||
|
||||
const unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
|
||||
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 unsigned int DSTAR_DATA_LENGTH_BYTES = 12U;
|
||||
const unsigned int DSTAR_DATA_LENGTH_BITS = DSTAR_DATA_LENGTH_BYTES * 8U;
|
||||
|
||||
const unsigned int DSTAR_END_SYNC_LENGTH_BYTES = 6U;
|
||||
const unsigned int DSTAR_END_SYNC_LENGTH_BITS = DSTAR_END_SYNC_LENGTH_BYTES * 8U;
|
||||
const uint8_t DSTAR_EOT_BYTES[] = {0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
const unsigned int DSTAR_EOT_LENGTH_BYTES = 6U;
|
||||
const unsigned int DSTAR_EOT_LENGTH_BITS = DSTAR_EOT_LENGTH_BYTES * 8U;
|
||||
|
||||
const unsigned int DSTAR_FRAME_SYNC_LENGTH_BYTES = 3U;
|
||||
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_LENGTH_BYTES = 3U;
|
||||
const uint8_t DSTAR_DATA_SYNC_LENGTH_BITS = DSTAR_DATA_SYNC_LENGTH_BYTES * 8U;
|
||||
|
||||
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_DATA_SYNC_BYTES[] = {0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16};
|
||||
|
||||
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_TEXT = 0x40U;
|
||||
const uint8_t DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
|
||||
|
||||
// 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};
|
||||
const uint8_t DSTAR_SCRAMBLER_BYTES[] = {0x70U, 0x4FU, 0x93U};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+136
-237
@@ -22,12 +22,18 @@
|
||||
#include "DStarRX.h"
|
||||
#include "Utils.h"
|
||||
|
||||
const unsigned int MAX_FRAMES = 150U;
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
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
|
||||
const uint32_t FRAME_SYNC_DATA = 0x00557650U;
|
||||
const uint32_t FRAME_SYNC_MASK = 0x00FFFFFFU;
|
||||
const uint8_t FRAME_SYNC_ERRS = 1U;
|
||||
const uint8_t FRAME_SYNC_ERRS = 2U;
|
||||
|
||||
// D-Star bit order version of 0x55 0x2D 0x16
|
||||
const uint32_t DATA_SYNC_DATA = 0x00AAB468U;
|
||||
@@ -231,24 +237,14 @@ const uint16_t CCITT_TABLE[] = {
|
||||
0xf78fU, 0xe606U, 0xd49dU, 0xc514U, 0xb1abU, 0xa022U, 0x92b9U, 0x8330U,
|
||||
0x7bc7U, 0x6a4eU, 0x58d5U, 0x495cU, 0x3de3U, 0x2c6aU, 0x1ef1U, 0x0f78U};
|
||||
|
||||
const uint16_t NOENDPTR = 9999U;
|
||||
|
||||
CDStarRX::CDStarRX() :
|
||||
m_pll(0U),
|
||||
m_prev(false),
|
||||
m_rxState(DSRXS_NONE),
|
||||
m_bitBuffer(),
|
||||
m_headerBuffer(),
|
||||
m_dataBuffer(),
|
||||
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_patternBuffer(0x00U),
|
||||
m_rxBuffer(),
|
||||
m_rxBufferBits(0U),
|
||||
m_dataBits(0U),
|
||||
m_mar(0U),
|
||||
m_pathMetric(),
|
||||
m_pathMemory0(),
|
||||
@@ -263,20 +259,14 @@ m_rssiCount(0U)
|
||||
|
||||
void CDStarRX::reset()
|
||||
{
|
||||
m_rxState = DSRXS_NONE;
|
||||
m_headerPtr = 0U;
|
||||
m_dataPtr = 0U;
|
||||
m_bitPtr = 0U;
|
||||
m_maxFrameCorr = 0;
|
||||
m_maxDataCorr = 0;
|
||||
m_startPtr = NOENDPTR;
|
||||
m_syncPtr = NOENDPTR;
|
||||
m_minSyncPtr = NOENDPTR;
|
||||
m_maxSyncPtr = NOENDPTR;
|
||||
m_frameCount = 0U;
|
||||
m_countdown = 0U;
|
||||
m_rssiAccum = 0U;
|
||||
m_rssiCount = 0U;
|
||||
m_pll = 0U;
|
||||
m_prev = false;
|
||||
m_rxState = DSRXS_NONE;
|
||||
m_patternBuffer = 0x00U;
|
||||
m_rxBufferBits = 0U;
|
||||
m_dataBits = 0U;
|
||||
m_rssiAccum = 0U;
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
|
||||
@@ -285,117 +275,125 @@ void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t lengt
|
||||
m_rssiAccum += rssi[i];
|
||||
m_rssiCount++;
|
||||
|
||||
q15_t sample = samples[i];
|
||||
bool bit = samples[i] < 0;
|
||||
|
||||
m_bitBuffer[m_bitPtr] <<= 1;
|
||||
if (sample < 0)
|
||||
m_bitBuffer[m_bitPtr] |= 0x01U;
|
||||
|
||||
m_dataBuffer[m_dataPtr] = sample;
|
||||
|
||||
switch (m_rxState) {
|
||||
case DSRXS_HEADER:
|
||||
processHeader(sample);
|
||||
break;
|
||||
case DSRXS_DATA:
|
||||
processData();
|
||||
break;
|
||||
default:
|
||||
processNone(sample);
|
||||
break;
|
||||
if (bit != m_prev) {
|
||||
if (m_pll < (PLLMAX / 2U))
|
||||
m_pll += INC;
|
||||
else
|
||||
m_pll -= INC;
|
||||
}
|
||||
|
||||
m_dataPtr++;
|
||||
if (m_dataPtr >= DSTAR_DATA_LENGTH_SAMPLES)
|
||||
m_dataPtr = 0U;
|
||||
m_prev = bit;
|
||||
|
||||
m_bitPtr++;
|
||||
if (m_bitPtr >= DSTAR_RADIO_SYMBOL_LENGTH)
|
||||
m_bitPtr = 0U;
|
||||
m_pll += PLLINC;
|
||||
|
||||
if (m_pll >= PLLMAX) {
|
||||
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(q15_t sample)
|
||||
void CDStarRX::processNone(bool bit)
|
||||
{
|
||||
m_patternBuffer <<= 1;
|
||||
if (bit)
|
||||
m_patternBuffer |= 0x01U;
|
||||
|
||||
// Fuzzy matching of the frame sync sequence
|
||||
bool ret = correlateFrameSync();
|
||||
if (ret) {
|
||||
m_countdown = 5U;
|
||||
|
||||
m_headerBuffer[m_headerPtr] = sample;
|
||||
m_headerPtr++;
|
||||
if (countBits32((m_patternBuffer & FRAME_SYNC_MASK) ^ FRAME_SYNC_DATA) <= FRAME_SYNC_ERRS) {
|
||||
DEBUG1("DStarRX: found frame sync in None");
|
||||
|
||||
::memset(m_rxBuffer, 0x00U, DSTAR_FEC_SECTION_LENGTH_BYTES);
|
||||
m_rxBufferBits = 0U;
|
||||
|
||||
m_rssiAccum = 0U;
|
||||
m_rssiCount = 0U;
|
||||
|
||||
m_rxState = DSRXS_HEADER;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Fuzzy matching of the data sync bit sequence
|
||||
ret = correlateDataSync();
|
||||
if (ret) {
|
||||
// Exact matching of the data sync bit sequence
|
||||
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) == 0U) {
|
||||
DEBUG1("DStarRX: found data sync in None");
|
||||
|
||||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
|
||||
m_rxState = DSRXS_DATA;
|
||||
// Suppress RSSI on the dummy sync message
|
||||
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(q15_t sample)
|
||||
void CDStarRX::processHeader(bool bit)
|
||||
{
|
||||
if (m_countdown > 0U) {
|
||||
correlateFrameSync();
|
||||
m_countdown--;
|
||||
}
|
||||
m_patternBuffer <<= 1;
|
||||
if (bit)
|
||||
m_patternBuffer |= 0x01U;
|
||||
|
||||
m_headerBuffer[m_headerPtr] = sample;
|
||||
m_headerPtr++;
|
||||
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
|
||||
m_rxBufferBits++;
|
||||
|
||||
// A full FEC header
|
||||
if (m_headerPtr == (DSTAR_FEC_SECTION_LENGTH_SAMPLES + DSTAR_RADIO_SYMBOL_LENGTH)) {
|
||||
uint8_t buffer[DSTAR_FEC_SECTION_LENGTH_BYTES];
|
||||
samplesToBits(m_headerBuffer, DSTAR_RADIO_SYMBOL_LENGTH, DSTAR_FEC_SECTION_LENGTH_SYMBOLS, buffer, DSTAR_FEC_SECTION_LENGTH_SAMPLES);
|
||||
|
||||
// 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 {
|
||||
if (m_rxBufferBits == DSTAR_FEC_SECTION_LENGTH_BITS) {
|
||||
// Process the scrambling, interleaving and FEC, then return if the chcksum was correct
|
||||
unsigned char header[DSTAR_HEADER_LENGTH_BYTES];
|
||||
bool ok = rxHeader(m_rxBuffer, header);
|
||||
if (ok) {
|
||||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
|
||||
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()
|
||||
void CDStarRX::processData(bool bit)
|
||||
{
|
||||
m_patternBuffer <<= 1;
|
||||
if (bit)
|
||||
m_patternBuffer |= 0x01U;
|
||||
|
||||
WRITE_BIT2(m_rxBuffer, m_rxBufferBits, bit);
|
||||
m_rxBufferBits++;
|
||||
|
||||
// Fuzzy matching of the end frame sequences
|
||||
if (countBits32((m_bitBuffer[m_bitPtr] & DSTAR_END_SYNC_MASK) ^ DSTAR_END_SYNC_DATA) <= END_SYNC_ERRS) {
|
||||
if (countBits32((m_patternBuffer & END_SYNC_MASK) ^ END_SYNC_DATA) <= END_SYNC_ERRS) {
|
||||
DEBUG1("DStarRX: Found end sync in Data");
|
||||
|
||||
io.setDecode(false);
|
||||
@@ -403,24 +401,35 @@ void CDStarRX::processData()
|
||||
|
||||
serial.writeDStarEOT();
|
||||
|
||||
m_maxFrameCorr = 0;
|
||||
m_maxDataCorr = 0;
|
||||
|
||||
m_rxState = DSRXS_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fuzzy matching of the data sync bit sequence
|
||||
if (m_minSyncPtr < m_maxSyncPtr) {
|
||||
if (m_dataPtr >= m_minSyncPtr && m_dataPtr <= m_maxSyncPtr)
|
||||
correlateDataSync();
|
||||
} else {
|
||||
if (m_dataPtr >= m_minSyncPtr || m_dataPtr <= m_maxSyncPtr)
|
||||
correlateDataSync();
|
||||
bool syncSeen = false;
|
||||
if (m_rxBufferBits >= (DSTAR_DATA_LENGTH_BITS - 3U)) {
|
||||
if (countBits32((m_patternBuffer & DATA_SYNC_MASK) ^ DATA_SYNC_DATA) <= DATA_SYNC_ERRS) {
|
||||
m_rxBufferBits = DSTAR_DATA_LENGTH_BITS;
|
||||
m_dataBits = MAX_SYNC_BITS;
|
||||
syncSeen = true;
|
||||
}
|
||||
}
|
||||
|
||||
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
|
||||
if (m_frameCount >= MAX_FRAMES) {
|
||||
// Check to see if the sync is arriving late
|
||||
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS && !syncSeen) {
|
||||
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");
|
||||
|
||||
io.setDecode(false);
|
||||
@@ -428,35 +437,24 @@ void CDStarRX::processData()
|
||||
|
||||
serial.writeDStarLost();
|
||||
|
||||
m_maxFrameCorr = 0;
|
||||
m_maxDataCorr = 0;
|
||||
|
||||
m_rxState = DSRXS_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Send a data frame to the host if the required number of bits have been received
|
||||
if (m_dataPtr == m_maxSyncPtr) {
|
||||
uint8_t buffer[DSTAR_DATA_LENGTH_BYTES + 2U];
|
||||
samplesToBits(m_dataBuffer, m_startPtr, DSTAR_DATA_LENGTH_SYMBOLS, buffer, DSTAR_DATA_LENGTH_SAMPLES);
|
||||
|
||||
if ((m_frameCount % 21U) == 0U) {
|
||||
if (m_frameCount == 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);
|
||||
// Send a data frame to the host if the required number of bits have been received, or if a data sync has been seen
|
||||
if (m_rxBufferBits == DSTAR_DATA_LENGTH_BITS) {
|
||||
if (syncSeen) {
|
||||
m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
|
||||
m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
|
||||
m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
|
||||
writeRSSIData(m_rxBuffer);
|
||||
} else {
|
||||
serial.writeDStarData(buffer, DSTAR_DATA_LENGTH_BYTES);
|
||||
}
|
||||
serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES);
|
||||
}
|
||||
|
||||
m_frameCount++;
|
||||
|
||||
m_maxFrameCorr = 0;
|
||||
m_maxDataCorr = 0;
|
||||
// Start the next frame
|
||||
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||
m_rxBufferBits = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,105 +500,6 @@ void CDStarRX::writeRSSIData(unsigned char* data)
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -37,21 +37,13 @@ public:
|
||||
void reset();
|
||||
|
||||
private:
|
||||
uint32_t m_pll;
|
||||
bool m_prev;
|
||||
DSRX_STATE m_rxState;
|
||||
uint32_t m_bitBuffer[DSTAR_RADIO_SYMBOL_LENGTH];
|
||||
q15_t m_headerBuffer[DSTAR_FEC_SECTION_LENGTH_SAMPLES + 2U * DSTAR_RADIO_SYMBOL_LENGTH];
|
||||
q15_t m_dataBuffer[DSTAR_DATA_LENGTH_SAMPLES];
|
||||
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;
|
||||
uint32_t m_patternBuffer;
|
||||
uint8_t m_rxBuffer[100U];
|
||||
unsigned int m_rxBufferBits;
|
||||
unsigned int m_dataBits;
|
||||
unsigned int m_mar;
|
||||
int m_pathMetric[4U];
|
||||
unsigned int m_pathMemory0[42U];
|
||||
@@ -62,12 +54,9 @@ private:
|
||||
uint32_t m_rssiAccum;
|
||||
uint16_t m_rssiCount;
|
||||
|
||||
void processNone(q15_t sample);
|
||||
void processHeader(q15_t sample);
|
||||
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 processNone(bool bit);
|
||||
void processHeader(bool bit);
|
||||
void processData(bool bit);
|
||||
void writeRSSIHeader(unsigned char* header);
|
||||
void writeRSSIData(unsigned char* data);
|
||||
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));
|
||||
|
||||
m_modFilter.L = DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
m_modFilter.L = DSTAR_RADIO_BIT_LENGTH;
|
||||
m_modFilter.phaseLength = GAUSSIAN_0_35_FILTER_PHASE_LEN;
|
||||
m_modFilter.pCoeffs = GAUSSIAN_0_35_FILTER;
|
||||
m_modFilter.pState = m_modState;
|
||||
@@ -252,8 +252,8 @@ void CDStarTX::process()
|
||||
m_buffer.get();
|
||||
|
||||
for (uint8_t j = 0U; j < 3U; j++) {
|
||||
for (uint8_t i = 0U; i < DSTAR_END_SYNC_LENGTH_BYTES; i++)
|
||||
m_poBuffer[m_poLen++] = DSTAR_END_SYNC_BYTES[i];
|
||||
for (uint8_t i = 0U; i < DSTAR_EOT_LENGTH_BYTES; i++)
|
||||
m_poBuffer[m_poLen++] = DSTAR_EOT_BYTES[i];
|
||||
}
|
||||
|
||||
m_poPtr = 0U;
|
||||
@@ -262,11 +262,11 @@ void CDStarTX::process()
|
||||
if (m_poLen > 0U) {
|
||||
uint16_t space = io.getSpace();
|
||||
|
||||
while (space > (8U * DSTAR_RADIO_SYMBOL_LENGTH)) {
|
||||
while (space > (8U * DSTAR_RADIO_BIT_LENGTH)) {
|
||||
uint8_t c = m_poBuffer[m_poPtr++];
|
||||
writeByte(c);
|
||||
|
||||
space -= 8U * DSTAR_RADIO_SYMBOL_LENGTH;
|
||||
space -= 8U * DSTAR_RADIO_BIT_LENGTH;
|
||||
|
||||
if (m_poPtr >= m_poLen) {
|
||||
m_poPtr = 0U;
|
||||
@@ -412,7 +412,7 @@ void CDStarTX::txHeader(const uint8_t* in, uint8_t* out) const
|
||||
void CDStarTX::writeByte(uint8_t c)
|
||||
{
|
||||
q15_t inBuffer[8U];
|
||||
q15_t outBuffer[DSTAR_RADIO_SYMBOL_LENGTH * 8U];
|
||||
q15_t outBuffer[DSTAR_RADIO_BIT_LENGTH * 8U];
|
||||
|
||||
uint8_t mask = 0x01U;
|
||||
|
||||
@@ -427,7 +427,7 @@ void CDStarTX::writeByte(uint8_t c)
|
||||
|
||||
::arm_fir_interpolate_q15(&m_modFilter, inBuffer, outBuffer, 8U);
|
||||
|
||||
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_SYMBOL_LENGTH * 8U);
|
||||
io.write(STATE_DSTAR, outBuffer, DSTAR_RADIO_BIT_LENGTH * 8U);
|
||||
}
|
||||
|
||||
void CDStarTX::setTXDelay(uint8_t delay)
|
||||
|
||||
@@ -34,6 +34,7 @@ m_callsignTimer(),
|
||||
m_timeoutTimer(),
|
||||
m_holdoffTimer(),
|
||||
m_kerchunkTimer(),
|
||||
m_kerchunkTX(true),
|
||||
m_ackMinTimer(),
|
||||
m_ackDelayTimer(),
|
||||
m_hangTimer(),
|
||||
@@ -183,7 +184,7 @@ 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, 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, bool kerchunkTX, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel)
|
||||
{
|
||||
m_useCOS = useCOS;
|
||||
m_cosInvert = cosInvert;
|
||||
@@ -191,7 +192,10 @@ uint8_t CFM::setMisc(uint16_t timeout, uint8_t timeoutLevel, uint8_t ctcssFreque
|
||||
m_rfAudioBoost = q15_t(rfAudioBoost);
|
||||
|
||||
m_timeoutTimer.setTimeout(timeout, 0U);
|
||||
|
||||
m_kerchunkTimer.setTimeout(kerchunkTime, 0U);
|
||||
m_kerchunkTX = kerchunkTX;
|
||||
|
||||
m_hangTimer.setTimeout(hangTime, 0U);
|
||||
|
||||
m_timeoutTone.setParams(timeoutLevel);
|
||||
@@ -275,17 +279,19 @@ void CFM::listeningState(bool validSignal)
|
||||
sendCallsign();
|
||||
}
|
||||
|
||||
insertSilence(50U);
|
||||
if (m_state == FS_RELAYING || (m_state == FS_KERCHUNK && m_kerchunkTX)) {
|
||||
insertSilence(50U);
|
||||
|
||||
beginRelaying();
|
||||
beginRelaying();
|
||||
|
||||
m_callsignTimer.start();
|
||||
m_callsignTimer.start();
|
||||
|
||||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
|
||||
DEBUG1("Change to STATE_FM");
|
||||
m_modemState = STATE_FM;
|
||||
DEBUG1("Change to STATE_FM");
|
||||
m_modemState = STATE_FM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,6 +306,19 @@ void CFM::kerchunkState(bool validSignal)
|
||||
sendCallsign();
|
||||
m_callsignTimer.start();
|
||||
}
|
||||
if (!m_kerchunkTX) {
|
||||
insertSilence(50U);
|
||||
|
||||
beginRelaying();
|
||||
|
||||
m_callsignTimer.start();
|
||||
|
||||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
|
||||
DEBUG1("Change to STATE_FM");
|
||||
m_modemState = STATE_FM;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
io.setDecode(false);
|
||||
|
||||
@@ -56,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 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, 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, bool kerchunkTX, uint8_t hangTime, bool useCOS, bool cosInvert, uint8_t rfAudioBoost, uint8_t maxDev, uint8_t rxLevel);
|
||||
|
||||
private:
|
||||
CFMKeyer m_callsign;
|
||||
@@ -72,6 +72,7 @@ private:
|
||||
CFMTimer m_timeoutTimer;
|
||||
CFMTimer m_holdoffTimer;
|
||||
CFMTimer m_kerchunkTimer;
|
||||
bool m_kerchunkTX;
|
||||
CFMTimer m_ackMinTimer;
|
||||
CFMTimer m_ackDelayTimer;
|
||||
CFMTimer m_hangTimer;
|
||||
|
||||
+13
-45
@@ -41,7 +41,6 @@ YSF PB8 output
|
||||
P25 PB9 output
|
||||
NXDN PB10 output
|
||||
POCSAG PB11 output
|
||||
FM PB12 output
|
||||
|
||||
RX PB0 analog input (ADC1_8)
|
||||
RSSI PB1 analog input (ADC2_9)
|
||||
@@ -85,9 +84,6 @@ USART1_RXD PA10 input (AF)
|
||||
#define PIN_POCSAG 11
|
||||
#define PORT_POCSAG GPIOB
|
||||
#define BB_POCSAG *((bitband_t)BITBAND_PERIPH(&PORT_POCSAG->ODR, PIN_POCSAG))
|
||||
#define PIN_FM 14
|
||||
#define PORT_FM GPIOB
|
||||
#define BB_FM *((bitband_t)BITBAND_PERIPH(&PORT_FM->ODR, PIN_FM))
|
||||
|
||||
#define PIN_RX 0
|
||||
#define PIN_RX_ADC_CH 8
|
||||
@@ -158,35 +154,16 @@ void GPIOConfigPin(GPIO_TypeDef *port_ptr, uint32_t pin, uint32_t mode_cnf_value
|
||||
#if defined(STM32F1_POG)
|
||||
void FancyLEDEffect()
|
||||
{
|
||||
int ledCount = 10;
|
||||
|
||||
bitband_t foo[] = {&BB_LED, &BB_COSLED, &BB_PTT, &BB_DMR, &BB_DSTAR, &BB_YSF, &BB_P25,
|
||||
#if defined(USE_ALTERNATE_NXDN_LEDS)
|
||||
NULL,
|
||||
#else
|
||||
&BB_NXDN,
|
||||
#endif
|
||||
#if defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||
NULL,
|
||||
#else
|
||||
&BB_POCSAG,
|
||||
#endif
|
||||
#if defined(USE_ALTERNATE_FM_LEDS)
|
||||
NULL};
|
||||
#else
|
||||
&BB_FM};
|
||||
#endif
|
||||
|
||||
for(int i=0; i<ledCount; i++){
|
||||
if(foo[i] != NULL)
|
||||
*foo[i] = 0x01;
|
||||
bitband_t foo[] = {&BB_LED, &BB_COSLED, &BB_PTT, &BB_DMR, &BB_DSTAR, &BB_YSF, &BB_P25};
|
||||
|
||||
for(int i=0; i<7; i++){
|
||||
*foo[i] = 0x01;
|
||||
}
|
||||
GPIOConfigPin(PORT_USART1_TXD, PIN_USART1_TXD, GPIO_CRL_MODE0_1);
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
||||
delay(SystemCoreClock/1000*100);
|
||||
for(int i=0; i<ledCount; i++){
|
||||
if(foo[i] != NULL)
|
||||
*foo[i] = 0x00;
|
||||
for(int i=0; i<7; i++){
|
||||
*foo[i] = 0x00;
|
||||
}
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||
delay(SystemCoreClock/1000*20);
|
||||
@@ -195,22 +172,18 @@ void FancyLEDEffect()
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||
|
||||
*foo[0] = 0x01;
|
||||
for(int i=1; i<ledCount; i++){
|
||||
for(int i=1; i<7; i++){
|
||||
delay(SystemCoreClock/1000*10);
|
||||
if (foo[i-1] != NULL)
|
||||
*foo[i-1] = 0x00;
|
||||
if (foo[i] != NULL)
|
||||
*foo[i] = 0x01;
|
||||
*foo[i-1] = 0x00;
|
||||
*foo[i] = 0x01;
|
||||
}
|
||||
for(int i=ledCount - 2; i>=0; i--) {
|
||||
for(int i=5; i>=0; i--){
|
||||
delay(SystemCoreClock/1000*10);
|
||||
if (foo[i+1] != NULL)
|
||||
*foo[i+1] = 0x00;
|
||||
if (foo[i] != NULL)
|
||||
*foo[i] = 0x01;
|
||||
*foo[i+1] = 0x00;
|
||||
*foo[i] = 0x01;
|
||||
}
|
||||
delay(SystemCoreClock/1000*10);
|
||||
*foo[0] = 0x00;
|
||||
*foo[5+1-6] = 0x00;
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x00;
|
||||
delay(SystemCoreClock/1000*10);
|
||||
*((bitband_t)BITBAND_PERIPH(&PORT_USART1_TXD->ODR, PIN_USART1_TXD)) = 0x01;
|
||||
@@ -255,9 +228,6 @@ static inline void GPIOInit()
|
||||
#if !defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||
GPIOConfigPin(PORT_POCSAG, PIN_POCSAG, GPIO_CRL_MODE0_1);
|
||||
#endif
|
||||
#if !defined(USE_ALTERNATE_FM_LEDS)
|
||||
GPIOConfigPin(PORT_FM, PIN_FM, GPIO_CRL_MODE0_1);
|
||||
#endif
|
||||
|
||||
GPIOConfigPin(PORT_RX, PIN_RX, 0);
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
@@ -495,8 +465,6 @@ void CIO::setFMInt(bool on)
|
||||
#if defined(USE_ALTERNATE_FM_LEDS)
|
||||
BB_DSTAR = !!on;
|
||||
BB_YSF = !!on;
|
||||
#else
|
||||
BB_FM = !!on;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion, P25, NXDN, and POCSAG modes.
|
||||
This is the source code of the MMDVM firmware that supports D-Star, DMR,
|
||||
System Fusion, P25, NXDN, POCSAG, and FM modes.
|
||||
|
||||
It runs on the Arduino Due, the ST-Micro STM32F1xxx, STM32F4xxx and STM32F7xxx processors, as well as the Teensy 3.1/3.2/3.5/3.6. What these platforms have in common is the use of an ARM Cortex-M3 or M4 processor with a clock speed greater than 70 MHz, and access to at least one analogue to digital converter and one digital to analogue converter.
|
||||
It runs on the Arduino Due, the ST-Micro STM32F1xxx, STM32F4xxx and STM32F7xxx
|
||||
processors, as well as the Teensy 3.1/3.2/3.5/3.6. What these platforms have in
|
||||
common is the use of an ARM Cortex-M3, M4, or M7 processors with a clock speed
|
||||
greater than 70 MHz, and access to at least one analogue to digital converter
|
||||
and one digital to analogue converter.
|
||||
|
||||
In order to build this software for the Arduino Due, you will need to edit a file within the Arduino GUI and that is detailed in the BUILD.txt file. The STM32 support is being supplied via the Coocox IDE with ARM GCC. The Teensy support uses Teensyduino.
|
||||
In order to build this software for the Arduino Due, you will need to edit a
|
||||
file within the Arduino GUI and that is detailed in the BUILD.txt file. The
|
||||
STM32 support is being supplied via the ARM GCC compiler. The Teensy support
|
||||
uses Teensyduino.
|
||||
|
||||
This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden.
|
||||
This software is licenced under the GPL v2 and is intended for amateur and
|
||||
educational use only. Use of this software for commercial purposes is strictly
|
||||
forbidden.
|
||||
|
||||
+5
-3
@@ -103,7 +103,7 @@ const uint8_t MMDVM_DEBUG5 = 0xF5U;
|
||||
#define HW_TYPE "MMDVM"
|
||||
#endif
|
||||
|
||||
#define DESCRIPTION "20200520 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)"
|
||||
#define DESCRIPTION "20200620 (D-Star/DMR/System Fusion/P25/NXDN/POCSAG/FM)"
|
||||
|
||||
#if defined(GITVERSION)
|
||||
#define concat(h, a, b, c) h " " a " " b " GitID #" c ""
|
||||
@@ -433,12 +433,13 @@ uint8_t CSerialPort::setFMParams3(const uint8_t* data, uint8_t length)
|
||||
|
||||
bool useCOS = (data[8U] & 0x01U) == 0x01U;
|
||||
bool cosInvert = (data[8U] & 0x02U) == 0x02U;
|
||||
bool kerchunkTX = (data[8U] & 0x04U) == 0x04U;
|
||||
|
||||
uint8_t rfAudioBoost = data[9U];
|
||||
uint8_t maxDev = data[10U];
|
||||
uint8_t rxLevel = data[11U];
|
||||
|
||||
return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, hangTime, useCOS, cosInvert, rfAudioBoost, maxDev, rxLevel);
|
||||
return fm.setMisc(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, kerchunkTX, hangTime, useCOS, cosInvert, rfAudioBoost, maxDev, rxLevel);
|
||||
}
|
||||
|
||||
uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
||||
@@ -592,7 +593,8 @@ void CSerialPort::process()
|
||||
m_buffer[0U] = c;
|
||||
m_ptr = 1U;
|
||||
m_len = 0U;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
m_ptr = 0U;
|
||||
m_len = 0U;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user