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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -59,7 +59,6 @@ m_colorCode(0U),
m_state(DMORXS_NONE), m_state(DMORXS_NONE),
m_n(0U), m_n(0U),
m_type(0U), m_type(0U),
m_rssiCount(0U),
m_rssi() m_rssi()
{ {
} }
@ -73,7 +72,6 @@ void CDMRDMORX::reset()
m_state = DMORXS_NONE; m_state = DMORXS_NONE;
m_startPtr = 0U; m_startPtr = 0U;
m_endPtr = NOENDPTR; m_endPtr = NOENDPTR;
m_rssiCount = 0U;
} }
void CDMRDMORX::samples(const q15_t* samples, const uint16_t* rssi, uint8_t length) 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) { switch (dataType) {
case DT_DATA_HEADER: case DT_DATA_HEADER:
DEBUG4("DMRDMORX: data header found pos/centre/threshold", m_syncPtr, centre, threshold); 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_state = DMORXS_DATA;
m_type = 0x00U; m_type = 0x00U;
break; break;
@ -155,32 +153,32 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi)
case DT_RATE_1_DATA: case DT_RATE_1_DATA:
if (m_state == DMORXS_DATA) { if (m_state == DMORXS_DATA) {
DEBUG4("DMRDMORX: data payload found pos/centre/threshold", m_syncPtr, centre, threshold); 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; m_type = dataType;
} }
break; break;
case DT_VOICE_LC_HEADER: case DT_VOICE_LC_HEADER:
DEBUG4("DMRDMORX: voice header found pos/centre/threshold", m_syncPtr, centre, threshold); 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; m_state = DMORXS_VOICE;
break; break;
case DT_VOICE_PI_HEADER: case DT_VOICE_PI_HEADER:
if (m_state == DMORXS_VOICE) { if (m_state == DMORXS_VOICE) {
DEBUG4("DMRDMORX: voice pi header found pos/centre/threshold", m_syncPtr, centre, threshold); 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; m_state = DMORXS_VOICE;
break; break;
case DT_TERMINATOR_WITH_LC: case DT_TERMINATOR_WITH_LC:
if (m_state == DMORXS_VOICE) { if (m_state == DMORXS_VOICE) {
DEBUG4("DMRDMORX: voice terminator found pos/centre/threshold", m_syncPtr, centre, threshold); DEBUG4("DMRDMORX: voice terminator found pos/centre/threshold", m_syncPtr, centre, threshold);
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); writeRSSIData(frame);
reset(); reset();
} }
break; break;
default: // DT_CSBK default: // DT_CSBK
DEBUG4("DMRDMORX: csbk found pos/centre/threshold", m_syncPtr, centre, threshold); DEBUG4("DMRDMORX: csbk found pos/centre/threshold", m_syncPtr, centre, threshold);
serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U); writeRSSIData(frame);
reset(); reset();
break; break;
} }
@ -188,24 +186,7 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi)
} else if (m_control == CONTROL_VOICE) { } else if (m_control == CONTROL_VOICE) {
// Voice sync // Voice sync
DEBUG4("DMRDMORX: voice sync found pos/centre/threshold", m_syncPtr, centre, threshold); DEBUG4("DMRDMORX: voice sync found pos/centre/threshold", m_syncPtr, centre, threshold);
#if defined(SEND_RSSI_DATA) writeRSSIData(frame);
// 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
m_state = DMORXS_VOICE; m_state = DMORXS_VOICE;
m_syncCount = 0U; m_syncCount = 0U;
m_n = 0U; m_n = 0U;
@ -225,28 +206,12 @@ bool CDMRDMORX::processSample(q15_t sample, uint16_t rssi)
} else { } else {
frame[0U] = ++m_n; 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); serial.writeDMRData(true, frame, DMR_FRAME_LENGTH_BYTES + 1U);
#endif
} else if (m_state == DMORXS_DATA) { } else if (m_state == DMORXS_DATA) {
if (m_type != 0x00U) { if (m_type != 0x00U) {
frame[0U] = CONTROL_DATA | m_type; 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_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_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre;
m_averagePtr = 0U; m_averagePtr = 0U;
m_rssiCount = 0U;
} else { } else {
m_threshold[m_averagePtr] = threshold; m_threshold[m_averagePtr] = threshold;
m_centre[m_averagePtr] = centre; 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_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_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre;
m_averagePtr = 0U; m_averagePtr = 0U;
m_rssiCount = 0U;
} else { } else {
m_threshold[m_averagePtr] = threshold; m_threshold[m_averagePtr] = threshold;
m_centre[m_averagePtr] = centre; 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) 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++) { for (uint8_t i = 0U; i < count; i++) {
@ -453,3 +401,27 @@ void CDMRDMORX::setColorCode(uint8_t colorCode)
m_colorCode = 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -58,13 +58,12 @@ private:
DMORX_STATE m_state; DMORX_STATE m_state;
uint8_t m_n; uint8_t m_n;
uint8_t m_type; uint8_t m_type;
uint16_t m_rssiCount;
uint16_t m_rssi[DMO_BUFFER_LENGTH_SAMPLES]; uint16_t m_rssi[DMO_BUFFER_LENGTH_SAMPLES];
bool processSample(q15_t sample, uint16_t rssi); bool processSample(q15_t sample, uint16_t rssi);
void correlateSync(bool first); void correlateSync(bool first);
void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); 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 #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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -65,7 +65,6 @@ m_delay(0U),
m_state(DMRRXS_NONE), m_state(DMRRXS_NONE),
m_n(0U), m_n(0U),
m_type(0U), m_type(0U),
m_rssiCount(0U),
m_rssi() m_rssi()
{ {
} }
@ -91,7 +90,6 @@ void CDMRSlotRX::reset()
m_state = DMRRXS_NONE; m_state = DMRRXS_NONE;
m_startPtr = 0U; m_startPtr = 0U;
m_endPtr = NOENDPTR; m_endPtr = NOENDPTR;
m_rssiCount = 0U;
} }
bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi) bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi)
@ -149,7 +147,7 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi)
switch (dataType) { switch (dataType) {
case DT_DATA_HEADER: case DT_DATA_HEADER:
DEBUG5("DMRSlotRX: data header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); 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_state = DMRRXS_DATA;
m_type = 0x00U; m_type = 0x00U;
break; break;
@ -158,33 +156,33 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi)
case DT_RATE_1_DATA: case DT_RATE_1_DATA:
if (m_state == DMRRXS_DATA) { if (m_state == DMRRXS_DATA) {
DEBUG5("DMRSlotRX: data payload found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); 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; m_type = dataType;
} }
break; break;
case DT_VOICE_LC_HEADER: case DT_VOICE_LC_HEADER:
DEBUG5("DMRSlotRX: voice header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); 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; m_state = DMRRXS_VOICE;
break; break;
case DT_VOICE_PI_HEADER: case DT_VOICE_PI_HEADER:
if (m_state == DMRRXS_VOICE) { if (m_state == DMRRXS_VOICE) {
DEBUG5("DMRSlotRX: voice pi header found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); 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; m_state = DMRRXS_VOICE;
break; break;
case DT_TERMINATOR_WITH_LC: case DT_TERMINATOR_WITH_LC:
if (m_state == DMRRXS_VOICE) { if (m_state == DMRRXS_VOICE) {
DEBUG5("DMRSlotRX: voice terminator found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); 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_state = DMRRXS_NONE;
m_endPtr = NOENDPTR; m_endPtr = NOENDPTR;
} }
break; break;
default: // DT_CSBK default: // DT_CSBK
DEBUG5("DMRSlotRX: csbk found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); 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_state = DMRRXS_NONE;
m_endPtr = NOENDPTR; m_endPtr = NOENDPTR;
break; break;
@ -193,24 +191,7 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi)
} else if (m_control == CONTROL_VOICE) { } else if (m_control == CONTROL_VOICE) {
// Voice sync // Voice sync
DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold); DEBUG5("DMRSlotRX: voice sync found slot/pos/centre/threshold", m_slot ? 2U : 1U, m_syncPtr, centre, threshold);
#if defined(SEND_RSSI_DATA) writeRSSIData(frame);
// 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
m_state = DMRRXS_VOICE; m_state = DMRRXS_VOICE;
m_syncCount = 0U; m_syncCount = 0U;
m_n = 0U; m_n = 0U;
@ -231,28 +212,12 @@ bool CDMRSlotRX::processSample(q15_t sample, uint16_t rssi)
} else { } else {
frame[0U] = ++m_n; 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); serial.writeDMRData(m_slot, frame, DMR_FRAME_LENGTH_BYTES + 1U);
#endif
} else if (m_state == DMRRXS_DATA) { } else if (m_state == DMRRXS_DATA) {
if (m_type != 0x00U) { if (m_type != 0x00U) {
frame[0U] = CONTROL_DATA | m_type; 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_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_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre;
m_averagePtr = 0U; m_averagePtr = 0U;
m_rssiCount = 0U;
} else { } else {
m_threshold[m_averagePtr] = threshold; m_threshold[m_averagePtr] = threshold;
m_centre[m_averagePtr] = centre; 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_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_centre[0U] = m_centre[1U] = m_centre[2U] = m_centre[3U] = centre;
m_averagePtr = 0U; m_averagePtr = 0U;
m_rssiCount = 0U;
} else { } else {
m_threshold[m_averagePtr] = threshold; m_threshold[m_averagePtr] = threshold;
m_centre[m_averagePtr] = centre; 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) 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) { 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; 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -62,12 +62,11 @@ private:
DMRRX_STATE m_state; DMRRX_STATE m_state;
uint8_t m_n; uint8_t m_n;
uint8_t m_type; uint8_t m_type;
uint16_t m_rssiCount;
uint16_t m_rssi[900U]; uint16_t m_rssi[900U];
void correlateSync(bool first); void correlateSync(bool first);
void samplesToBits(uint16_t start, uint8_t count, uint8_t* buffer, uint16_t offset, q15_t centre, q15_t threshold); 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 #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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -275,7 +275,7 @@ void CDStarRX::reset()
m_samplesPtr = 0U; 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++) { for (uint16_t i = 0U; i < length; i++) {
m_samples[m_samplesPtr] = samples[i]; m_samples[m_samplesPtr] = samples[i];
@ -298,13 +298,13 @@ void CDStarRX::samples(const q15_t* samples, uint8_t length)
switch (m_rxState) { switch (m_rxState) {
case DSRXS_NONE: case DSRXS_NONE:
processNone(bit); processNone(bit, rssi[i]);
break; break;
case DSRXS_HEADER: case DSRXS_HEADER:
processHeader(bit); processHeader(bit, rssi[i]);
break; break;
case DSRXS_DATA: case DSRXS_DATA:
processData(bit); processData(bit, rssi[i]);
break; break;
default: default:
break; 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; m_patternBuffer <<= 1;
if (bit) if (bit)
@ -341,7 +341,8 @@ void CDStarRX::processNone(bool bit)
io.setDecode(true); io.setDecode(true);
io.setADCDetection(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); ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
m_rxBufferBits = 0U; 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; m_patternBuffer <<= 1;
if (bit) if (bit)
@ -370,7 +371,7 @@ void CDStarRX::processHeader(bool bit)
io.setDecode(true); io.setDecode(true);
io.setADCDetection(true); io.setADCDetection(true);
serial.writeDStarHeader(header, DSTAR_HEADER_LENGTH_BYTES); writeRSSIHeader(header, rssi);
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); ::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U);
m_rxBufferBits = 0U; 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; m_patternBuffer <<= 1;
if (bit) if (bit)
@ -457,9 +458,10 @@ void CDStarRX::processData(bool bit)
m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U]; m_rxBuffer[9U] = DSTAR_DATA_SYNC_BYTES[9U];
m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U]; m_rxBuffer[10U] = DSTAR_DATA_SYNC_BYTES[10U];
m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U]; m_rxBuffer[11U] = DSTAR_DATA_SYNC_BYTES[11U];
} writeRSSIData(m_rxBuffer, rssi);
} else {
serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES); serial.writeDStarData(m_rxBuffer, DSTAR_DATA_LENGTH_BYTES);
}
// Start the next frame // Start the next frame
::memset(m_rxBuffer, 0x00U, DSTAR_DATA_LENGTH_BYTES + 2U); ::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) bool CDStarRX::rxHeader(uint8_t* in, uint8_t* out)
{ {
int i; 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]; 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -32,7 +32,7 @@ class CDStarRX {
public: public:
CDStarRX(); 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(); void reset();
@ -54,9 +54,11 @@ private:
q15_t m_samples[DSTAR_DATA_SYNC_LENGTH_BITS]; q15_t m_samples[DSTAR_DATA_SYNC_LENGTH_BITS];
uint8_t m_samplesPtr; uint8_t m_samplesPtr;
void processNone(bool bit); void processNone(bool bit, uint16_t rssi);
void processHeader(bool bit); void processHeader(bool bit, uint16_t rssi);
void processData(bool bit); 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); bool rxHeader(uint8_t* in, uint8_t* out);
void acs(int* metric); void acs(int* metric);
void viterbiDecode(int* data); 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -457,7 +457,7 @@ void CDStarTX::writeByte(uint8_t c)
void CDStarTX::setTXDelay(uint8_t delay) 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 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -41,7 +41,7 @@ private:
CSerialRB m_buffer; CSerialRB m_buffer;
arm_fir_instance_q15 m_modFilter; arm_fir_instance_q15 m_modFilter;
q15_t m_modState[60U]; // NoTaps + BlockSize - 1, 12 + 40 - 1 plus some spare 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_poLen;
uint16_t m_poPtr; uint16_t m_poPtr;
uint16_t m_txDelay; // In bytes 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) 2015 by Jim Mclaughlin KI6ZUM
* Copyright (C) 2016 by Colin Durbridge G4EML * Copyright (C) 2016 by Colin Durbridge G4EML
* *
@ -184,7 +184,7 @@ void CIO::process()
q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; q15_t GMSKVals[RX_BLOCK_SIZE + 1U];
::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize); ::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) { if (m_dmrEnable || m_ysfEnable || m_p25Enable) {
@ -199,17 +199,17 @@ void CIO::process()
} }
if (m_ysfEnable) if (m_ysfEnable)
ysfRX.samples(C4FSKVals, blockSize); ysfRX.samples(C4FSKVals, rssi, blockSize);
if (m_p25Enable) if (m_p25Enable)
p25RX.samples(C4FSKVals, blockSize); p25RX.samples(C4FSKVals, rssi, blockSize);
} }
} else if (m_modemState == STATE_DSTAR) { } else if (m_modemState == STATE_DSTAR) {
if (m_dstarEnable) { if (m_dstarEnable) {
q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; q15_t GMSKVals[RX_BLOCK_SIZE + 1U];
::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize); ::arm_fir_fast_q15(&m_GMSKFilter, samples, GMSKVals, blockSize);
dstarRX.samples(GMSKVals, blockSize); dstarRX.samples(GMSKVals, rssi, blockSize);
} }
} else if (m_modemState == STATE_DMR) { } else if (m_modemState == STATE_DMR) {
if (m_dmrEnable) { if (m_dmrEnable) {
@ -231,14 +231,14 @@ void CIO::process()
q15_t C4FSKVals[RX_BLOCK_SIZE + 1U]; q15_t C4FSKVals[RX_BLOCK_SIZE + 1U];
::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize); ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize);
ysfRX.samples(C4FSKVals, blockSize); ysfRX.samples(C4FSKVals, rssi, blockSize);
} }
} else if (m_modemState == STATE_P25) { } else if (m_modemState == STATE_P25) {
if (m_p25Enable) { if (m_p25Enable) {
q15_t C4FSKVals[RX_BLOCK_SIZE + 1U]; q15_t C4FSKVals[RX_BLOCK_SIZE + 1U];
::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize); ::arm_fir_fast_q15(&m_C4FSKFilter, samples, C4FSKVals, blockSize);
p25RX.samples(C4FSKVals, blockSize); p25RX.samples(C4FSKVals, rssi, blockSize);
} }
} else if (m_modemState == STATE_DSTARCAL) { } else if (m_modemState == STATE_DSTARCAL) {
q15_t GMSKVals[RX_BLOCK_SIZE + 1U]; 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -40,7 +40,7 @@ public:
void setADCDetection(bool detect); void setADCDetection(bool detect);
void setMode(); 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); 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) 2015 by Jim Mclaughlin KI6ZUM
* Copyright (C) 2016 by Colin Durbridge G4EML * Copyright (C) 2016 by Colin Durbridge G4EML
* *
@ -77,7 +77,7 @@ const uint16_t DC_OFFSET = 2048U;
extern "C" { extern "C" {
void ADC_Handler() void ADC_Handler()
{ {
io.interrupt(0U); io.interrupt();
} }
} }
@ -101,7 +101,7 @@ void CIO::initInt()
void CIO::startInt() void CIO::startInt()
{ {
if (ADC->ADC_ISR & ADC_ISR_EOC_Chan) // Ensure there was an End-of-Conversion and we read the ISR reg 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 // Set up the ADC
NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector NVIC_EnableIRQ(ADC_IRQn); // Enable ADC interrupt vector
@ -164,7 +164,7 @@ void CIO::startInt()
digitalWrite(PIN_LED, HIGH); 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 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; uint8_t control = MARK_NONE;

View File

@ -1,6 +1,7 @@
/* /*
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM * Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016 by Andy Uribe CA6JAU * 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -213,7 +214,7 @@ extern "C" {
void TIM2_IRQHandler() { void TIM2_IRQHandler() {
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
io.interrupt(0U); io.interrupt();
} }
} }
} }
@ -280,7 +281,7 @@ void CIO::initInt()
void CIO::startInt() void CIO::startInt()
{ {
if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET)) if ((ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) != RESET))
io.interrupt(0U); io.interrupt();
// Init the ADC // Init the ADC
GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitTypeDef GPIO_InitStruct;
@ -421,7 +422,7 @@ void CIO::startInt()
GPIO_SetBits(PORT_LED, PIN_LED); GPIO_SetBits(PORT_LED, PIN_LED);
} }
void CIO::interrupt(uint8_t source) void CIO::interrupt()
{ {
uint8_t control = MARK_NONE; uint8_t control = MARK_NONE;
uint16_t sample = DC_OFFSET; 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -45,15 +45,8 @@ const uint16_t DC_OFFSET = 2048U;
extern "C" { extern "C" {
void adc0_isr() void adc0_isr()
{ {
io.interrupt(0U); io.interrupt();
} }
#if defined(SEND_RSSI_DATA)
void adc1_isr()
{
io.interrupt(1U);
}
#endif
} }
void CIO::initInt() void CIO::initInt()
@ -116,7 +109,6 @@ void CIO::startInt()
ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
sum1 = (sum1 / 2U) | 0x8000U; sum1 = (sum1 / 2U) | 0x8000U;
ADC1_PG = sum1; ADC1_PG = sum1;
#endif #endif
#if defined(EXTERNAL_OSC) #if defined(EXTERNAL_OSC)
@ -149,42 +141,33 @@ void CIO::startInt()
digitalWrite(PIN_LED, HIGH); digitalWrite(PIN_LED, HIGH);
} }
void CIO::interrupt(uint8_t source) void CIO::interrupt()
{ {
if (source == 0U) { // ADC0 uint8_t control = MARK_NONE;
uint8_t control = MARK_NONE; uint16_t sample = DC_OFFSET;
uint16_t sample = DC_OFFSET;
m_txBuffer.get(sample, control); m_txBuffer.get(sample, control);
*(int16_t *)&(DAC0_DAT0L) = sample; *(int16_t *)&(DAC0_DAT0L) = sample;
if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { if ((ADC0_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
sample = ADC0_RA; sample = ADC0_RA;
m_rxBuffer.put(sample, control); m_rxBuffer.put(sample, control);
} }
#if defined(SEND_RSSI_DATA) #if defined(SEND_RSSI_DATA)
if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) {
if ((ADC1_SC1A & ADC_SC1_COCO) == ADC_SC1_COCO) { uint16_t rssi = ADC1_RA;
uint16_t rssi = ADC1_RA; m_rssiBuffer.put(rssi);
m_rssiBuffer.put(rssi); } else {
} m_rssiBuffer.put(0U);
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++;
} }
ADC1_SC1A = PIN_RSSI; // Start the next RSSI conversion
#else
m_rssiBuffer.put(0U);
#endif
m_watchdog++;
} }
bool CIO::getCOSInt() 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -73,7 +73,7 @@ void CP25RX::reset()
m_threshold = 0; 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++) { for (uint16_t i = 0U; i < length; i++) {
bool bit = samples[i] < 0; bool bit = samples[i] < 0;
@ -95,7 +95,7 @@ void CP25RX::samples(const q15_t* samples, uint8_t length)
if (m_state == P25RXS_NONE) if (m_state == P25RXS_NONE)
processNone(samples[i]); processNone(samples[i]);
else else
processData(samples[i]); processData(samples[i], rssi[i]);
} }
} }
} }
@ -173,7 +173,7 @@ void CP25RX::processNone(q15_t sample)
m_symbolPtr = 0U; m_symbolPtr = 0U;
} }
void CP25RX::processData(q15_t sample) void CP25RX::processData(q15_t sample, uint16_t rssi)
{ {
sample -= m_centre; sample -= m_centre;
@ -251,7 +251,7 @@ void CP25RX::processData(q15_t sample)
} else { } else {
m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; 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 // Start the next frame
::memset(m_outBuffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 3U); ::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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -31,7 +31,7 @@ class CP25RX {
public: public:
CP25RX(); 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(); void reset();
@ -51,7 +51,8 @@ private:
q15_t m_threshold; q15_t m_threshold;
void processNone(q15_t sample); 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 #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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -41,7 +41,7 @@ private:
arm_fir_instance_q15 m_lpFilter; arm_fir_instance_q15 m_lpFilter;
q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare 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 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_poLen;
uint16_t m_poPtr; uint16_t m_poPtr;
uint16_t m_txDelay; 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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -73,7 +73,7 @@ void CYSFRX::reset()
m_threshold = 0; 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++) { for (uint16_t i = 0U; i < length; i++) {
bool bit = samples[i] < 0; bool bit = samples[i] < 0;
@ -95,7 +95,7 @@ void CYSFRX::samples(const q15_t* samples, uint8_t length)
if (m_state == YSFRXS_NONE) if (m_state == YSFRXS_NONE)
processNone(samples[i]); processNone(samples[i]);
else else
processData(samples[i]); processData(samples[i], rssi[i]);
} }
} }
} }
@ -173,7 +173,7 @@ void CYSFRX::processNone(q15_t sample)
m_symbolPtr = 0U; m_symbolPtr = 0U;
} }
void CYSFRX::processData(q15_t sample) void CYSFRX::processData(q15_t sample, uint16_t rssi)
{ {
sample -= m_centre; sample -= m_centre;
@ -233,7 +233,7 @@ void CYSFRX::processData(q15_t sample)
} else { } else {
m_outBuffer[0U] = m_lostCount == (MAX_SYNC_FRAMES - 1U) ? 0x01U : 0x00U; 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 // Start the next frame
::memset(m_outBuffer, 0x00U, YSF_FRAME_LENGTH_BYTES + 3U); ::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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -31,7 +31,7 @@ class CYSFRX {
public: public:
CYSFRX(); 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(); void reset();
@ -51,7 +51,8 @@ private:
q15_t m_threshold; q15_t m_threshold;
void processNone(q15_t sample); 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 #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 * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -39,7 +39,7 @@ private:
CSerialRB m_buffer; CSerialRB m_buffer;
arm_fir_instance_q15 m_modFilter; arm_fir_instance_q15 m_modFilter;
q15_t m_modState[70U]; // NoTaps + BlockSize - 1, 42 + 20 - 1 plus some spare 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_poLen;
uint16_t m_poPtr; uint16_t m_poPtr;
uint16_t m_txDelay; uint16_t m_txDelay;