From 0a51b4c34eff6ef46c0e58bbdfbb6c7a93666d04 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 20 Apr 2020 21:57:21 +0100 Subject: [PATCH] Store FM output in a ring buffer. --- FM.cpp | 24 +++++++++++-- FM.h | 2 ++ FMRB.cpp | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ FMRB.h | 70 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 FMRB.cpp create mode 100644 FMRB.h diff --git a/FM.cpp b/FM.cpp index 17e6462..1385c5b 100644 --- a/FM.cpp +++ b/FM.cpp @@ -31,6 +31,8 @@ q15_t FILTER_COEFFS[] = { const uint16_t FILTER_COEFFS_LEN = 101U; +const uint16_t OUTPUT_BUFFER_SIZE = 1000U; + CFM::CFM() : m_filter(), m_filterState(), @@ -48,7 +50,8 @@ m_holdoffTimer(), m_kerchunkTimer(), m_ackMinTimer(), m_ackDelayTimer(), -m_hangTimer() +m_hangTimer(), +m_ringBuffer(OUTPUT_BUFFER_SIZE) { ::memset(m_filterState, 0x00U, 230U * sizeof(q15_t)); @@ -86,11 +89,28 @@ void CFM::samples(bool cos, q15_t* samples, uint8_t length) m_ctcssTX.getAudio(output, length); - io.write(STATE_FM, output, length); + for (uint8_t i = 0U; i < length; i++) { + bool ret = m_ringBuffer.put(output[i]); + if (!ret) { + DEBUG1("Overflow in the FM ring buffer"); + break; + } + } } void CFM::process() { + uint16_t space = io.getSpace(); + uint16_t data = m_ringBuffer.getData(); + if (data < space) + space = data; + + for (uint16_t i = 0U; i < space; i++) { + q15_t sample; + m_ringBuffer.get(sample); + + io.write(STATE_FM, &sample, 1U); + } } void CFM::reset() diff --git a/FM.h b/FM.h index 963f29b..54ca54c 100644 --- a/FM.h +++ b/FM.h @@ -26,6 +26,7 @@ #include "FMTimeout.h" #include "FMKeyer.h" #include "FMTimer.h" +#include "FMRB.h" enum FM_STATE { FS_LISTENING, @@ -69,6 +70,7 @@ private: CFMTimer m_ackMinTimer; CFMTimer m_ackDelayTimer; CFMTimer m_hangTimer; + CFMRB m_ringBuffer; void stateMachine(bool validSignal, uint8_t length); void listeningState(bool validSignal); diff --git a/FMRB.cpp b/FMRB.cpp new file mode 100644 index 0000000..7f46195 --- /dev/null +++ b/FMRB.cpp @@ -0,0 +1,102 @@ +/* +TX fifo control - Copyright (C) KI6ZUM 2015 +Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include "FMRB.h" + +CFMRB::CFMRB(uint16_t length) : +m_length(length), +m_head(0U), +m_tail(0U), +m_full(false), +m_overflow(false) +{ + m_samples = new q15_t[length]; +} + +uint16_t CFMRB::getSpace() const +{ + uint16_t n = 0U; + + if (m_tail == m_head) + n = m_full ? 0U : m_length; + else if (m_tail < m_head) + n = m_length - m_head + m_tail; + else + n = m_tail - m_head; + + if (n > m_length) + n = 0U; + + return n; +} + +uint16_t CFMRB::getData() const +{ + if (m_tail == m_head) + return m_full ? m_length : 0U; + else if (m_tail < m_head) + return m_head - m_tail; + else + return m_length - m_tail + m_head; +} + +bool CFMRB::put(q15_t sample) +{ + if (m_full) { + m_overflow = true; + return false; + } + + m_samples[m_head] = sample; + + m_head++; + if (m_head >= m_length) + m_head = 0U; + + if (m_head == m_tail) + m_full = true; + + return true; +} + +bool CFMRB::get(q15_t& sample) +{ + if (m_head == m_tail && !m_full) + return false; + + sample = m_samples[m_tail]; + + m_full = false; + + m_tail++; + if (m_tail >= m_length) + m_tail = 0U; + + return true; +} + +bool CFMRB::hasOverflowed() +{ + bool overflow = m_overflow; + + m_overflow = false; + + return overflow; +} diff --git a/FMRB.h b/FMRB.h new file mode 100644 index 0000000..3d641cf --- /dev/null +++ b/FMRB.h @@ -0,0 +1,70 @@ +/* +Serial fifo control - Copyright (C) KI6ZUM 2015 +Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#if !defined(FMRB_H) +#define FMRB_H + +#if defined(STM32F4XX) +#include "stm32f4xx.h" +#elif defined(STM32F7XX) +#include "stm32f7xx.h" +#elif defined(STM32F105xC) +#include "stm32f1xx.h" +#include +#else +#include +#endif + +#if defined(__SAM3X8E__) || defined(STM32F105xC) +#define ARM_MATH_CM3 +#elif defined(STM32F7XX) +#define ARM_MATH_CM7 +#elif defined(STM32F4XX) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) +#define ARM_MATH_CM4 +#else +#error "Unknown processor type" +#endif + +#include + +class CFMRB { +public: + CFMRB(uint16_t length); + + uint16_t getSpace() const; + + uint16_t getData() const; + + bool put(q15_t sample); + + bool get(q15_t& sample); + + bool hasOverflowed(); + +private: + uint16_t m_length; + volatile q15_t* m_samples; + volatile uint16_t m_head; + volatile uint16_t m_tail; + volatile bool m_full; + bool m_overflow; +}; + +#endif