mirror of https://github.com/g4klx/MMDVM.git
Merge remote-tracking branch 'g4klx/master'
This commit is contained in:
commit
048888f45b
96
DMRDMORX.cpp
96
DMRDMORX.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017 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
|
||||
|
@ -59,7 +59,6 @@ m_colorCode(0U),
|
|||
m_state(DMORXS_NONE),
|
||||
m_n(0U),
|
||||
m_type(0U),
|
||||
m_rssiCount(0U),
|
||||
m_rssi()
|
||||
{
|
||||
}
|
||||
|
@ -73,7 +72,6 @@ void CDMRDMORX::reset()
|
|||
m_state = DMORXS_NONE;
|
||||
m_startPtr = 0U;
|
||||
m_endPtr = NOENDPTR;
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
void CDMRDMORX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
|
||||
|
@ -146,7 +144,7 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi)
|
|||
switch (dataType) {
|
||||
case DT_DATA_HEADER:
|
||||
DEBUG4("DMRDMORX: data header found pos/centre/threshold", m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
m_state = DMORXS_DATA;
|
||||
m_type = 0x00U;
|
||||
break;
|
||||
|
@ -155,32 +153,32 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi)
|
|||
case DT_RATE_1_DATA:
|
||||
if (m_state == DMORXS_DATA) {
|
||||
DEBUG4("DMRDMORX: data payload found pos/centre/threshold", m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
m_type = dataType;
|
||||
}
|
||||
break;
|
||||
case DT_VOICE_LC_HEADER:
|
||||
DEBUG4("DMRDMORX: voice header found pos/centre/threshold", m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
m_state = DMORXS_VOICE;
|
||||
break;
|
||||
case DT_VOICE_PI_HEADER:
|
||||
if (m_state == DMORXS_VOICE) {
|
||||
DEBUG4("DMRDMORX: voice pi header found pos/centre/threshold", m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
}
|
||||
m_state = DMORXS_VOICE;
|
||||
break;
|
||||
case DT_TERMINATOR_WITH_LC:
|
||||
if (m_state == DMORXS_VOICE) {
|
||||
DEBUG4("DMRDMORX: voice terminator found pos/centre/threshold", m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
reset();
|
||||
}
|
||||
break;
|
||||
default: // DT_CSBK
|
||||
DEBUG4("DMRDMORX: csbk found pos/centre/threshold", m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
reset();
|
||||
break;
|
||||
}
|
||||
|
@ -188,24 +186,7 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi)
|
|||
} else if (m_control == CONTROL_VOICE) {
|
||||
// Voice sync
|
||||
DEBUG4("DMRDMORX: voice sync found pos/centre/threshold", m_syncPtr, centre, threshold);
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
// Send RSSI data approximately every second
|
||||
if (m_rssiCount == 2U) {
|
||||
// Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end
|
||||
uint16_t rssi_avg = avgRSSI(m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U, DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES);
|
||||
frame[34U] = (rssi_avg >> 8) & 0xFFU;
|
||||
frame[35U] = (rssi_avg >> 0) & 0xFFU;
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 3U);
|
||||
} else {
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
}
|
||||
|
||||
m_rssiCount++;
|
||||
if (m_rssiCount >= 16U)
|
||||
m_rssiCount = 0U;
|
||||
#else
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
writeRSSIData(frame);
|
||||
m_state = DMORXS_VOICE;
|
||||
m_syncCount = 0U;
|
||||
m_n = 0U;
|
||||
|
@ -225,28 +206,12 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi)
|
|||
} else {
|
||||
frame[0U] = ++m_n;
|
||||
}
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
// Send RSSI data approximately every second
|
||||
if (m_rssiCount == 2U) {
|
||||
// Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end
|
||||
uint16_t rssi_avg = avgRSSI(m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U, DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES);
|
||||
frame[34U] = (rssi_avg >> 8) & 0xFFU;
|
||||
frame[35U] = (rssi_avg >> 0) & 0xFFU;
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 3U);
|
||||
} else {
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
}
|
||||
|
||||
m_rssiCount++;
|
||||
if (m_rssiCount >= 16U)
|
||||
m_rssiCount = 0U;
|
||||
#else
|
||||
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
} else if (m_state == DMORXS_DATA) {
|
||||
if (m_type != 0x00U) {
|
||||
frame[0U] = CONTROL_DATA | m_type;
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -337,7 +302,6 @@ void CDMRDMORX::correlateSync(bool first)
|
|||
m_threshold[0U] = m_threshold[1U] = m_threshold[2U] = m_threshold[3U] = threshold;
|
||||
m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre;
|
||||
m_averagePtr = 0U;
|
||||
m_rssiCount = 0U;
|
||||
} else {
|
||||
m_threshold[m_averagePtr] = threshold;
|
||||
m_centre[m_averagePtr] = centre;
|
||||
|
@ -373,7 +337,6 @@ void CDMRDMORX::correlateSync(bool first)
|
|||
m_threshold[0U] = m_threshold[1U] = m_threshold[2U] = m_threshold[3U] = threshold;
|
||||
m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre;
|
||||
m_averagePtr = 0U;
|
||||
m_rssiCount = 0U;
|
||||
} else {
|
||||
m_threshold[m_averagePtr] = threshold;
|
||||
m_centre[m_averagePtr] = centre;
|
||||
|
@ -400,21 +363,6 @@ void CDMRDMORX::correlateSync(bool first)
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t CDMRDMORX::avgRSSI(uint16_t start, uint16_t count)
|
||||
{
|
||||
float rssi_tmp = 0.0F;
|
||||
|
||||
for (uint16_t i = 0U; i < count; i++) {
|
||||
rssi_tmp += float(m_rssi[start]);
|
||||
|
||||
start++;
|
||||
if (start >= DMO_BUFFER_LENGTH_SAMPLES)
|
||||
start -= DMO_BUFFER_LENGTH_SAMPLES;
|
||||
}
|
||||
|
||||
return uint16_t(rssi_tmp / count);
|
||||
}
|
||||
|
||||
void CDMRDMORX::samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold)
|
||||
{
|
||||
for (uint8_t i = 0U; i < count; i++) {
|
||||
|
@ -453,3 +401,27 @@ void CDMRDMORX::setColorCode(uint8_t colorCode)
|
|||
m_colorCode = colorCode;
|
||||
}
|
||||
|
||||
void CDMRDMORX::writeRSSIData(uint8_t* frame)
|
||||
{
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
// Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end
|
||||
uint16_t start = m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U;
|
||||
|
||||
uint32_t accum = 0U;
|
||||
for (uint16_t i = 0U; i < (DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES); i++) {
|
||||
accum += m_rssi[start];
|
||||
|
||||
start++;
|
||||
if (start >= DMO_BUFFER_LENGTH_SAMPLES)
|
||||
start -= DMO_BUFFER_LENGTH_SAMPLES;
|
||||
}
|
||||
|
||||
uint16_t avg = accum / (DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES);
|
||||
frame[34U] = (avg >> 8) & 0xFFU;
|
||||
frame[35U] = (avg >> 0) & 0xFFU;
|
||||
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 3U);
|
||||
#else
|
||||
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017 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
|
||||
|
@ -58,13 +58,12 @@ private:
|
|||
DMORX_STATE m_state;
|
||||
uint8_t m_n;
|
||||
uint8_t m_type;
|
||||
uint16_t m_rssiCount;
|
||||
uint16_t m_rssi[DMO_BUFFER_LENGTH_SAMPLES];
|
||||
|
||||
bool processSample(q15_t sample, uint16_t rssi);
|
||||
void correlateSync(bool first);
|
||||
void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold);
|
||||
uint16_t avgRSSI(uint16_t start, uint16_t count);
|
||||
void writeRSSIData(uint8_t* frame);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,7 +41,7 @@ private:
|
|||
CSerialRB m_fifo;
|
||||
arm_fir_instance_q15 m_modFilter;
|
||||
q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
||||
uint8_t m_poBuffer[80U];
|
||||
uint8_t m_poBuffer[1200U];
|
||||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017 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
|
||||
|
@ -65,7 +65,6 @@ m_delay(0U),
|
|||
m_state(DMRRXS_NONE),
|
||||
m_n(0U),
|
||||
m_type(0U),
|
||||
m_rssiCount(0U),
|
||||
m_rssi()
|
||||
{
|
||||
}
|
||||
|
@ -91,7 +90,6 @@ void CDMRSlotRX::reset()
|
|||
m_state = DMRRXS_NONE;
|
||||
m_startPtr = 0U;
|
||||
m_endPtr = NOENDPTR;
|
||||
m_rssiCount = 0U;
|
||||
}
|
||||
|
||||
bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi)
|
||||
|
@ -149,7 +147,7 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi)
|
|||
switch (dataType) {
|
||||
case DT_DATA_HEADER:
|
||||
DEBUG5("DMRSlotRX: data header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
m_state = DMRRXS_DATA;
|
||||
m_type = 0x00U;
|
||||
break;
|
||||
|
@ -158,33 +156,33 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi)
|
|||
case DT_RATE_1_DATA:
|
||||
if (m_state == DMRRXS_DATA) {
|
||||
DEBUG5("DMRSlotRX: data payload found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
m_type = dataType;
|
||||
}
|
||||
break;
|
||||
case DT_VOICE_LC_HEADER:
|
||||
DEBUG5("DMRSlotRX: voice header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
m_state = DMRRXS_VOICE;
|
||||
break;
|
||||
case DT_VOICE_PI_HEADER:
|
||||
if (m_state == DMRRXS_VOICE) {
|
||||
DEBUG5("DMRSlotRX: voice pi header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
}
|
||||
m_state = DMRRXS_VOICE;
|
||||
break;
|
||||
case DT_TERMINATOR_WITH_LC:
|
||||
if (m_state == DMRRXS_VOICE) {
|
||||
DEBUG5("DMRSlotRX: voice terminator found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
m_state = DMRRXS_NONE;
|
||||
m_endPtr = NOENDPTR;
|
||||
}
|
||||
break;
|
||||
default: // DT_CSBK
|
||||
DEBUG5("DMRSlotRX: csbk found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
m_state = DMRRXS_NONE;
|
||||
m_endPtr = NOENDPTR;
|
||||
break;
|
||||
|
@ -193,24 +191,7 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi)
|
|||
} else if (m_control == CONTROL_VOICE) {
|
||||
// Voice sync
|
||||
DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
// Send RSSI data approximately every second
|
||||
if (m_rssiCount == 2U) {
|
||||
// Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end
|
||||
uint16_t rssi_avg = avgRSSI(m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U, DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES);
|
||||
frame[34U] = (rssi_avg >> 8) & 0xFFU;
|
||||
frame[35U] = (rssi_avg >> 0) & 0xFFU;
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 3U);
|
||||
} else {
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
}
|
||||
|
||||
m_rssiCount++;
|
||||
if (m_rssiCount >= 16U)
|
||||
m_rssiCount = 0U;
|
||||
#else
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
writeRSSIData(frame);
|
||||
m_state = DMRRXS_VOICE;
|
||||
m_syncCount = 0U;
|
||||
m_n = 0U;
|
||||
|
@ -231,28 +212,12 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi)
|
|||
} else {
|
||||
frame[0U] = ++m_n;
|
||||
}
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
// Send RSSI data approximately every second
|
||||
if (m_rssiCount == 2U) {
|
||||
// Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end
|
||||
uint16_t rssi_avg = avgRSSI(m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U, DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES);
|
||||
frame[34U] = (rssi_avg >> 8) & 0xFFU;
|
||||
frame[35U] = (rssi_avg >> 0) & 0xFFU;
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 3U);
|
||||
} else {
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
}
|
||||
|
||||
m_rssiCount++;
|
||||
if (m_rssiCount >= 16U)
|
||||
m_rssiCount = 0U;
|
||||
#else
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
} else if (m_state == DMRRXS_DATA) {
|
||||
if (m_type != 0x00U) {
|
||||
frame[0U] = CONTROL_DATA | m_type;
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(frame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +284,6 @@ void CDMRSlotRX::correlateSync(bool first)
|
|||
m_threshold[0U] = m_threshold[1U] = m_threshold[2U] = m_threshold[3U] = threshold;
|
||||
m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre;
|
||||
m_averagePtr = 0U;
|
||||
m_rssiCount = 0U;
|
||||
} else {
|
||||
m_threshold[m_averagePtr] = threshold;
|
||||
m_centre[m_averagePtr] = centre;
|
||||
|
@ -345,7 +309,6 @@ void CDMRSlotRX::correlateSync(bool first)
|
|||
m_threshold[0U] = m_threshold[1U] = m_threshold[2U] = m_threshold[3U] = threshold;
|
||||
m_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre;
|
||||
m_averagePtr = 0U;
|
||||
m_rssiCount = 0U;
|
||||
} else {
|
||||
m_threshold[m_averagePtr] = threshold;
|
||||
m_centre[m_averagePtr] = centre;
|
||||
|
@ -366,21 +329,6 @@ void CDMRSlotRX::correlateSync(bool first)
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t CDMRSlotRX::avgRSSI(uint16_t start, uint16_t count)
|
||||
{
|
||||
float rssi_tmp = 0.0F;
|
||||
|
||||
for (uint16_t i = 0U; i < count; i++) {
|
||||
rssi_tmp += float(m_rssi[start]);
|
||||
|
||||
start++;
|
||||
if (start >= 900U)
|
||||
start -= 900U;
|
||||
}
|
||||
|
||||
return uint16_t(rssi_tmp / count);
|
||||
}
|
||||
|
||||
void CDMRSlotRX::samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold)
|
||||
{
|
||||
for (uint8_t i = 0U; i < count; i++, start += DMR_RADIO_SYMBOL_LENGTH) {
|
||||
|
@ -420,3 +368,22 @@ void CDMRSlotRX::setDelay(uint8_t delay)
|
|||
m_delay = delay;
|
||||
}
|
||||
|
||||
void CDMRSlotRX::writeRSSIData(uint8_t* frame)
|
||||
{
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
// Calculate RSSI average over a burst period. We don't take into account 2.5 ms at the beginning and 2.5 ms at the end
|
||||
uint16_t start = m_startPtr + DMR_SYNC_LENGTH_SAMPLES / 2U;
|
||||
|
||||
uint32_t accum = 0U;
|
||||
for (uint16_t i = 0U; i < (DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES); i++)
|
||||
accum += m_rssi[start++];
|
||||
|
||||
uint16_t avg = accum / (DMR_FRAME_LENGTH_SAMPLES - DMR_SYNC_LENGTH_SAMPLES);
|
||||
frame[34U] = (avg >> 8) & 0xFFU;
|
||||
frame[35U] = (avg >> 0) & 0xFFU;
|
||||
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 3U);
|
||||
#else
|
||||
serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017 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
|
||||
|
@ -62,12 +62,11 @@ private:
|
|||
DMRRX_STATE m_state;
|
||||
uint8_t m_n;
|
||||
uint8_t m_type;
|
||||
uint16_t m_rssiCount;
|
||||
uint16_t m_rssi[900U];
|
||||
|
||||
void correlateSync(bool first);
|
||||
void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold);
|
||||
uint16_t avgRSSI(uint16_t start, uint16_t count);
|
||||
void writeRSSIData(uint8_t* frame);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
53
DStarRX.cpp
53
DStarRX.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017 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
|
||||
|
@ -275,7 +275,7 @@ void CDStarRX::reset()
|
|||
m_samplesPtr = 0U;
|
||||
}
|
||||
|
||||
void CDStarRX::samples(const q15_t* samples, uint8_t length)
|
||||
void CDStarRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
|
||||
{
|
||||
for (uint16_t i = 0U; i < length; i++) {
|
||||
m_samples[m_samplesPtr] = samples[i];
|
||||
|
@ -298,13 +298,13 @@ void CDStarRX::samples(const q15_t* samples, uint8_t length)
|
|||
|
||||
switch (m_rxState) {
|
||||
case DSRXS_NONE:
|
||||
processNone(bit);
|
||||
processNone(bit, rssi[i]);
|
||||
break;
|
||||
case DSRXS_HEADER:
|
||||
processHeader(bit);
|
||||
processHeader(bit, rssi[i]);
|
||||
break;
|
||||
case DSRXS_DATA:
|
||||
processData(bit);
|
||||
processData(bit, rssi[i]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -317,7 +317,7 @@ void CDStarRX::samples(const q15_t* samples, uint8_t length)
|
|||
}
|
||||
}
|
||||
|
||||
void CDStarRX::processNone(bool bit)
|
||||
void CDStarRX::processNone(bool bit, uint16_t rssi)
|
||||
{
|
||||
m_patternBuffer <<= 1;
|
||||
if (bit)
|
||||
|
@ -341,7 +341,8 @@ void CDStarRX::processNone(bool bit)
|
|||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
|
||||
serial.writeDStarData(DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES);
|
||||
::memcpy(m_rxBuffer, DSTAR_DATA_SYNC_BYTES, DSTAR_DATA_LENGTH_BYTES);
|
||||
writeRSSIData(m_rxBuffer, rssi);
|
||||
|
||||
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||
m_rxBufferBits = 0U;
|
||||
|
@ -352,7 +353,7 @@ void CDStarRX::processNone(bool bit)
|
|||
}
|
||||
}
|
||||
|
||||
void CDStarRX::processHeader(bool bit)
|
||||
void CDStarRX::processHeader(bool bit, uint16_t rssi)
|
||||
{
|
||||
m_patternBuffer <<= 1;
|
||||
if (bit)
|
||||
|
@ -370,7 +371,7 @@ void CDStarRX::processHeader(bool bit)
|
|||
io.setDecode(true);
|
||||
io.setADCDetection(true);
|
||||
|
||||
serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES);
|
||||
writeRSSIHeader(header, rssi);
|
||||
|
||||
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||
m_rxBufferBits = 0U;
|
||||
|
@ -384,7 +385,7 @@ void CDStarRX::processHeader(bool bit)
|
|||
}
|
||||
}
|
||||
|
||||
void CDStarRX::processData(bool bit)
|
||||
void CDStarRX::processData(bool bit, uint16_t rssi)
|
||||
{
|
||||
m_patternBuffer <<= 1;
|
||||
if (bit)
|
||||
|
@ -457,9 +458,10 @@ void CDStarRX::processData(bool bit)
|
|||
m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
|
||||
m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
|
||||
m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
|
||||
}
|
||||
|
||||
serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES);
|
||||
writeRSSIData(m_rxBuffer, rssi);
|
||||
} else {
|
||||
serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES);
|
||||
}
|
||||
|
||||
// Start the next frame
|
||||
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||
|
@ -467,6 +469,30 @@ void CDStarRX::processData(bool bit)
|
|||
}
|
||||
}
|
||||
|
||||
void CDStarRX::writeRSSIHeader(unsigned char* header, uint16_t rssi)
|
||||
{
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
header[41U] = (rssi >> 8) & 0xFFU;
|
||||
header[42U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES + 2U);
|
||||
#else
|
||||
serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES + 0U);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CDStarRX::writeRSSIData(unsigned char* data, uint16_t rssi)
|
||||
{
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
data[12U] = (rssi >> 8) & 0xFFU;
|
||||
data[13U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeDStarData(data, DSTAR_DATA_LENGTH_BYTES + 2U);
|
||||
#else
|
||||
serial.writeDStarData(data, DSTAR_DATA_LENGTH_BYTES + 0U);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out)
|
||||
{
|
||||
int i;
|
||||
|
@ -682,4 +708,3 @@ bool CDStarRX::checksum(const uint8_t* header) const
|
|||
|
||||
return crc8[0U] == header[DSTAR_HEADER_LENGTH_BYTES - 2U] && crc8[1U] == header[DSTAR_HEADER_LENGTH_BYTES - 1U];
|
||||
}
|
||||
|
||||
|
|
12
DStarRX.h
12
DStarRX.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017 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
|
||||
|
@ -32,7 +32,7 @@ class CDStarRX {
|
|||
public:
|
||||
CDStarRX();
|
||||
|
||||
void samples(const q15_t* samples, uint8_t length);
|
||||
void samples(const q15_t* samples, const uint16_t* rssi, uint8_t length);
|
||||
|
||||
void reset();
|
||||
|
||||
|
@ -54,9 +54,11 @@ private:
|
|||
q15_t m_samples[DSTAR_DATA_SYNC_LENGTH_BITS];
|
||||
uint8_t m_samplesPtr;
|
||||
|
||||
void processNone(bool bit);
|
||||
void processHeader(bool bit);
|
||||
void processData(bool bit);
|
||||
void processNone(bool bit, uint16_t rssi);
|
||||
void processHeader(bool bit, uint16_t rssi);
|
||||
void processData(bool bit, uint16_t rssi);
|
||||
void writeRSSIHeader(unsigned char* header, uint16_t rssi);
|
||||
void writeRSSIData(unsigned char* data, uint16_t rssi);
|
||||
bool rxHeader(uint8_t* in, uint8_t* out);
|
||||
void acs(int* metric);
|
||||
void viterbiDecode(int* data);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017 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
|
||||
|
@ -457,7 +457,7 @@ void CDStarTX::writeByte(uint8_t c)
|
|||
|
||||
void CDStarTX::setTXDelay(uint8_t delay)
|
||||
{
|
||||
m_txDelay = 150U + uint16_t(delay) * 6U; // 250ms + tx delay
|
||||
m_txDelay = 300U + uint16_t(delay) * 6U; // 250ms + tx delay
|
||||
}
|
||||
|
||||
uint16_t CDStarTX::getSpace() const
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017 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
|
||||
|
@ -41,7 +41,7 @@ private:
|
|||
CSerialRB m_buffer;
|
||||
arm_fir_instance_q15 m_modFilter;
|
||||
q15_t m_modState[60U]; // NoTaps + BlockSize - 1, 12 + 40 - 1 plus some spare
|
||||
uint8_t m_poBuffer[500U];
|
||||
uint8_t m_poBuffer[600U];
|
||||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay; // In bytes
|
||||
|
|
14
IO.cpp
14
IO.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
|
@ -184,7 +184,7 @@ void CIO::process()
|
|||
q15_t GMSKVals[RX_BLOCK_SIZE + 1U];
|
||||
::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize);
|
||||
|
||||
dstarRX.samples(GMSKVals, blockSize);
|
||||
dstarRX.samples(GMSKVals, rssi, blockSize);
|
||||
}
|
||||
|
||||
if (m_dmrEnable || m_ysfEnable || m_p25Enable) {
|
||||
|
@ -199,17 +199,17 @@ void CIO::process()
|
|||
}
|
||||
|
||||
if (m_ysfEnable)
|
||||
ysfRX.samples(C4FSKVals, blockSize);
|
||||
ysfRX.samples(C4FSKVals, rssi, blockSize);
|
||||
|
||||
if (m_p25Enable)
|
||||
p25RX.samples(C4FSKVals, blockSize);
|
||||
p25RX.samples(C4FSKVals, rssi, blockSize);
|
||||
}
|
||||
} else if (m_modemState == STATE_DSTAR) {
|
||||
if (m_dstarEnable) {
|
||||
q15_t GMSKVals[RX_BLOCK_SIZE + 1U];
|
||||
::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize);
|
||||
|
||||
dstarRX.samples(GMSKVals, blockSize);
|
||||
dstarRX.samples(GMSKVals, rssi, blockSize);
|
||||
}
|
||||
} else if (m_modemState == STATE_DMR) {
|
||||
if (m_dmrEnable) {
|
||||
|
@ -231,14 +231,14 @@ void CIO::process()
|
|||
q15_t C4FSKVals[RX_BLOCK_SIZE + 1U];
|
||||
::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize);
|
||||
|
||||
ysfRX.samples(C4FSKVals, blockSize);
|
||||
ysfRX.samples(C4FSKVals, rssi, blockSize);
|
||||
}
|
||||
} else if (m_modemState == STATE_P25) {
|
||||
if (m_p25Enable) {
|
||||
q15_t C4FSKVals[RX_BLOCK_SIZE + 1U];
|
||||
::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize);
|
||||
|
||||
p25RX.samples(C4FSKVals, blockSize);
|
||||
p25RX.samples(C4FSKVals, rssi, blockSize);
|
||||
}
|
||||
} else if (m_modemState == STATE_DSTARCAL) {
|
||||
q15_t GMSKVals[RX_BLOCK_SIZE + 1U];
|
||||
|
|
4
IO.h
4
IO.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017 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
|
||||
|
@ -40,7 +40,7 @@ public:
|
|||
void setADCDetection(bool detect);
|
||||
void setMode();
|
||||
|
||||
void interrupt(uint8_t source);
|
||||
void interrupt();
|
||||
|
||||
void setParameters(bool rxInvert, bool txInvert, bool pttInvert, uint8_t rxLevel, uint8_t cwIdTXLevel, uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel);
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015 by Jim Mclaughlin KI6ZUM
|
||||
* Copyright (C) 2016 by Colin Durbridge G4EML
|
||||
*
|
||||
|
@ -77,7 +77,7 @@ const uint16_t DC_OFFSET = 2048U;
|
|||
extern "C" {
|
||||
void ADC_Handler()
|
||||
{
|
||||
io.interrupt(0U);
|
||||
io.interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ void CIO::initInt()
|
|||
void CIO::startInt()
|
||||
{
|
||||
if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg
|
||||
io.interrupt(0U);
|
||||
io.interrupt();
|
||||
|
||||
// Set up the ADC
|
||||
NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector
|
||||
|
@ -164,7 +164,7 @@ void CIO::startInt()
|
|||
digitalWrite(PIN_LED, HIGH);
|
||||
}
|
||||
|
||||
void CIO::interrupt(uint8_t source)
|
||||
void CIO::interrupt()
|
||||
{
|
||||
if ((ADC->ADC_ISR & ADC_ISR_EOC_Chan) == ADC_ISR_EOC_Chan) { // Ensure there was an End-of-Conversion and we read the ISR reg
|
||||
uint8_t control = MARK_NONE;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM
|
||||
* Copyright (C) 2016 by Andy Uribe CA6JAU
|
||||
* Copyright (C) 2017 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
|
||||
|
@ -213,7 +214,7 @@ extern "C" {
|
|||
void TIM2_IRQHandler() {
|
||||
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
|
||||
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
|
||||
io.interrupt(0U);
|
||||
io.interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +281,7 @@ void CIO::initInt()
|
|||
void CIO::startInt()
|
||||
{
|
||||
if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET))
|
||||
io.interrupt(0U);
|
||||
io.interrupt();
|
||||
|
||||
// Init the ADC
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
|
@ -421,7 +422,7 @@ void CIO::startInt()
|
|||
GPIO_SetBits(PORT_LED, PIN_LED);
|
||||
}
|
||||
|
||||
void CIO::interrupt(uint8_t source)
|
||||
void CIO::interrupt()
|
||||
{
|
||||
uint8_t control = MARK_NONE;
|
||||
uint16_t sample = DC_OFFSET;
|
||||
|
|
59
IOTeensy.cpp
59
IOTeensy.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017 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
|
||||
|
@ -45,15 +45,8 @@ const uint16_t DC_OFFSET = 2048U;
|
|||
extern "C" {
|
||||
void adc0_isr()
|
||||
{
|
||||
io.interrupt(0U);
|
||||
io.interrupt();
|
||||
}
|
||||
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
void adc1_isr()
|
||||
{
|
||||
io.interrupt(1U);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CIO::initInt()
|
||||
|
@ -116,7 +109,6 @@ void CIO::startInt()
|
|||
ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
|
||||
sum1 = (sum1 / 2U) | 0x8000U;
|
||||
ADC1_PG = sum1;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(EXTERNAL_OSC)
|
||||
|
@ -149,42 +141,33 @@ void CIO::startInt()
|
|||
digitalWrite(PIN_LED, HIGH);
|
||||
}
|
||||
|
||||
void CIO::interrupt(uint8_t source)
|
||||
void CIO::interrupt()
|
||||
{
|
||||
if (source == 0U) { // ADC0
|
||||
uint8_t control = MARK_NONE;
|
||||
uint16_t sample = DC_OFFSET;
|
||||
uint8_t control = MARK_NONE;
|
||||
uint16_t sample = DC_OFFSET;
|
||||
|
||||
m_txBuffer.get(sample, control);
|
||||
*(int16_t *)&(DAC0_DAT0L) = sample;
|
||||
m_txBuffer.get(sample, control);
|
||||
*(int16_t *)&(DAC0_DAT0L) = sample;
|
||||
|
||||
if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
|
||||
sample = ADC0_RA;
|
||||
m_rxBuffer.put(sample, control);
|
||||
}
|
||||
if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
|
||||
sample = ADC0_RA;
|
||||
m_rxBuffer.put(sample, control);
|
||||
}
|
||||
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
|
||||
if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
|
||||
uint16_t rssi = ADC1_RA;
|
||||
m_rssiBuffer.put(rssi);
|
||||
}
|
||||
else {
|
||||
m_rssiBuffer.put(0U);
|
||||
}
|
||||
ADC1_SC1A = ADC_SC1_AIEN | PIN_RSSI; //start the next RSSI conversion
|
||||
|
||||
#else
|
||||
m_rssiBuffer.put(0U);
|
||||
#endif
|
||||
|
||||
|
||||
m_watchdog++;
|
||||
if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
|
||||
uint16_t rssi = ADC1_RA;
|
||||
m_rssiBuffer.put(rssi);
|
||||
} else {
|
||||
m_rssiBuffer.put(0U);
|
||||
}
|
||||
|
||||
ADC1_SC1A = PIN_RSSI; // Start the next RSSI conversion
|
||||
#else
|
||||
m_rssiBuffer.put(0U);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
m_watchdog++;
|
||||
}
|
||||
|
||||
bool CIO::getCOSInt()
|
||||
|
|
21
P25RX.cpp
21
P25RX.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017 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
|
||||
|
@ -73,7 +73,7 @@ void CP25RX::reset()
|
|||
m_threshold = 0;
|
||||
}
|
||||
|
||||
void CP25RX::samples(const q15_t* samples, uint8_t length)
|
||||
void CP25RX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
|
||||
{
|
||||
for (uint16_t i = 0U; i < length; i++) {
|
||||
bool bit = samples[i] < 0;
|
||||
|
@ -95,7 +95,7 @@ void CP25RX::samples(const q15_t* samples, uint8_t length)
|
|||
if (m_state == P25RXS_NONE)
|
||||
processNone(samples[i]);
|
||||
else
|
||||
processData(samples[i]);
|
||||
processData(samples[i], rssi[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ void CP25RX::processNone(q15_t sample)
|
|||
m_symbolPtr = 0U;
|
||||
}
|
||||
|
||||
void CP25RX::processData(q15_t sample)
|
||||
void CP25RX::processData(q15_t sample, uint16_t rssi)
|
||||
{
|
||||
sample -= m_centre;
|
||||
|
||||
|
@ -251,7 +251,7 @@ void CP25RX::processData(q15_t sample)
|
|||
} else {
|
||||
m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U;
|
||||
|
||||
serial.writeP25Ldu(m_outBuffer, P25_LDU_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSILdu(m_outBuffer, rssi);
|
||||
|
||||
// Start the next frame
|
||||
::memset(m_outBuffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 3U);
|
||||
|
@ -260,3 +260,14 @@ void CP25RX::processData(q15_t sample)
|
|||
}
|
||||
}
|
||||
|
||||
void CP25RX::writeRSSILdu(uint8_t* ldu, uint16_t rssi)
|
||||
{
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
ldu[216U] = (rssi >> 8) & 0xFFU;
|
||||
ldu[217U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeP25Ldu(ldu, P25_LDU_FRAME_LENGTH_BYTES + 3U);
|
||||
#else
|
||||
serial.writeP25Ldu(ldu, P25_LDU_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
}
|
||||
|
|
7
P25RX.h
7
P25RX.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017 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
|
||||
|
@ -31,7 +31,7 @@ class CP25RX {
|
|||
public:
|
||||
CP25RX();
|
||||
|
||||
void samples(const q15_t* samples, uint8_t length);
|
||||
void samples(const q15_t* samples, const uint16_t* rssi, uint8_t length);
|
||||
|
||||
void reset();
|
||||
|
||||
|
@ -51,7 +51,8 @@ private:
|
|||
q15_t m_threshold;
|
||||
|
||||
void processNone(q15_t sample);
|
||||
void processData(q15_t sample);
|
||||
void processData(q15_t sample, uint16_t rssi);
|
||||
void writeRSSILdu(uint8_t* data, uint16_t rssi);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
4
P25TX.h
4
P25TX.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017 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
|
||||
|
@ -41,7 +41,7 @@ private:
|
|||
arm_fir_instance_q15 m_lpFilter;
|
||||
q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
||||
q15_t m_lpState[70U]; // NoTaps + BlockSize - 1, 44 + 20 - 1 plus some spare
|
||||
uint8_t m_poBuffer[920U];
|
||||
uint8_t m_poBuffer[1200U];
|
||||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion and P25.
|
||||
This is the source code of the MMDVM firmware that supports D-Star, DMR, System Fusion and P25 modes.
|
||||
|
||||
It runs on the Arduino Due and the ST-Micro STM32F4xx platforms. Support for the Teensy (3.1/3.2 and 3.5/3.6) is being added.
|
||||
It runs on the Arduino Due, the ST-Micro STM32F407-DISCO and STM32F446-NUCLEO, 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. A Cortex-M7 processor is also probably adequate.
|
||||
|
||||
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 is via the latest beta of Teensyduino.
|
||||
|
||||
|
|
21
YSFRX.cpp
21
YSFRX.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2009-2017 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
|
||||
|
@ -73,7 +73,7 @@ void CYSFRX::reset()
|
|||
m_threshold = 0;
|
||||
}
|
||||
|
||||
void CYSFRX::samples(const q15_t* samples, uint8_t length)
|
||||
void CYSFRX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length)
|
||||
{
|
||||
for (uint16_t i = 0U; i < length; i++) {
|
||||
bool bit = samples[i] < 0;
|
||||
|
@ -95,7 +95,7 @@ void CYSFRX::samples(const q15_t* samples, uint8_t length)
|
|||
if (m_state == YSFRXS_NONE)
|
||||
processNone(samples[i]);
|
||||
else
|
||||
processData(samples[i]);
|
||||
processData(samples[i], rssi[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ void CYSFRX::processNone(q15_t sample)
|
|||
m_symbolPtr = 0U;
|
||||
}
|
||||
|
||||
void CYSFRX::processData(q15_t sample)
|
||||
void CYSFRX::processData(q15_t sample, uint16_t rssi)
|
||||
{
|
||||
sample -= m_centre;
|
||||
|
||||
|
@ -233,7 +233,7 @@ void CYSFRX::processData(q15_t sample)
|
|||
} else {
|
||||
m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U;
|
||||
|
||||
serial.writeYSFData(m_outBuffer, YSF_FRAME_LENGTH_BYTES + 1U);
|
||||
writeRSSIData(m_outBuffer, rssi);
|
||||
|
||||
// Start the next frame
|
||||
::memset(m_outBuffer, 0x00U, YSF_FRAME_LENGTH_BYTES + 3U);
|
||||
|
@ -242,3 +242,14 @@ void CYSFRX::processData(q15_t sample)
|
|||
}
|
||||
}
|
||||
|
||||
void CYSFRX::writeRSSIData(uint8_t* data, uint16_t rssi)
|
||||
{
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
data[120U] = (rssi >> 8) & 0xFFU;
|
||||
data[121U] = (rssi >> 0) & 0xFFU;
|
||||
|
||||
serial.writeYSFData(data, YSF_FRAME_LENGTH_BYTES + 3U);
|
||||
#else
|
||||
serial.writeYSFData(data, YSF_FRAME_LENGTH_BYTES + 1U);
|
||||
#endif
|
||||
}
|
||||
|
|
7
YSFRX.h
7
YSFRX.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017 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
|
||||
|
@ -31,7 +31,7 @@ class CYSFRX {
|
|||
public:
|
||||
CYSFRX();
|
||||
|
||||
void samples(const q15_t* samples, uint8_t length);
|
||||
void samples(const q15_t* samples, const uint16_t* rssi, uint8_t length);
|
||||
|
||||
void reset();
|
||||
|
||||
|
@ -51,7 +51,8 @@ private:
|
|||
q15_t m_threshold;
|
||||
|
||||
void processNone(q15_t sample);
|
||||
void processData(q15_t sample);
|
||||
void processData(q15_t sample, uint16_t rssi);
|
||||
void writeRSSIData(unsigned char* data, uint16_t rssi);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
4
YSFTX.h
4
YSFTX.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017 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
|
||||
|
@ -39,7 +39,7 @@ private:
|
|||
CSerialRB m_buffer;
|
||||
arm_fir_instance_q15 m_modFilter;
|
||||
q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare
|
||||
uint8_t m_poBuffer[920U];
|
||||
uint8_t m_poBuffer[1200U];
|
||||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay;
|
||||
|
|
Loading…
Reference in New Issue