diff --git a/openrtx/include/protocols/M17/Synchronizer.hpp b/openrtx/include/protocols/M17/Synchronizer.hpp new file mode 100644 index 00000000..163398af --- /dev/null +++ b/openrtx/include/protocols/M17/Synchronizer.hpp @@ -0,0 +1,129 @@ +/*************************************************************************** + * Copyright (C) 2024 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * * + * * + * 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 * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + **************************************************************************/ + +#ifndef SYNCHRONIZER_H +#define SYNCHRONIZER_H + +#include +#include +#include "Correlator.hpp" + +/** + * Frame syncronizer class. It allows to find the best sampling point for a + * baseband stream, given a syncword. + */ +template < size_t SYNCW_SIZE, size_t SAMPLES_PER_SYM > +class Synchronizer +{ +public: + + /** + * Constructor. + * + * @param sync_word: symbols of the target syncword. + */ + Synchronizer(std::array< int8_t, SYNCW_SIZE >&& sync_word) : + syncword(std::move(sync_word)) { } + + /** + * Destructor. + */ + ~Synchronizer() { } + + /** + * Perform an update step of the syncronizer. + * + * @param correlator: correlator object to be used to compute the convolution + * product with the syncword. + * @param posTh: threshold to detect a positive correlation peak. + * @param negTh: threshold to detect a negative correlation peak. + * @return +1 if a positive correlation peak has been found, -1 if a negative + * correlation peak has been found an zero otherwise. + */ + int8_t update(Correlator< SYNCW_SIZE, SAMPLES_PER_SYM >& correlator, + const int32_t posTh, const int32_t negTh) + { + int32_t sign = 0; + int32_t corr = correlator.convolve(syncword); + bool trigger = (corr > posTh) || (corr < negTh); + + if(trigger == true) + { + if(triggered == false) + { + values.fill(0); + triggered = true; + } + + values[correlator.sampleIndex()] = corr; + } + else + { + if(triggered) + { + // Calculate the sampling index on the falling edge. + triggered = false; + sampIndex = 0; + + int32_t peak = corr; + uint8_t index = 0; + for(auto val : values) + { + if(std::abs(val) > std::abs(peak)) + { + peak = val; + sampIndex = index; + } + + index += 1; + } + + if(values[index] >= 0) + sign = 1; + else + sign = -1; + } + } + + return sign; + } + + /** + * Get the best sampling index equivalent to the last correlation peak + * found. This value is meaningful only when the update() function returned + * a value different from zero. + * + * @return the optimal sampling index. + */ + size_t samplingIndex() + { + return sampIndex; + } + +private: + + std::array< int8_t, SYNCW_SIZE > syncword; ///< Target syncword + std::array< int32_t, SAMPLES_PER_SYM > values; ///< Correlation history + bool triggered; ///< Peak found + uint8_t sampIndex; ///< Optimal sampling point +}; + +#endif