Add RSSI reporting for all modes.

c4fmdemod
Jonathan Naylor 2017-01-05 18:59:15 +00:00
parent 8777c2b29c
commit 57fde3afcc
19 changed files with 198 additions and 226 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -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];
}

View File

@ -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);

View File

@ -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

View File

@ -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
View File

@ -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
View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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()

View File

@ -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
}

View File

@ -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

View File

@ -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;

View File

@ -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
}

View File

@ -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

View File

@ -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;