/*************************************************************************** * Copyright (C) 2022 - 2025 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 M17PRBS_H #define M17PRBS_H #ifndef __cplusplus #error This header is C++ only! #endif #include namespace M17 { /** * Pseudo random number generator compliant with M17 PRBS9 specification. */ class PRBS9 { public: /** * Constructor. */ PRBS9() : state(1), syncCnt(0), synced(false) { } /** * Destructor. */ ~PRBS9() { } /** * Reset the generator state. */ void reset() { state = 1; syncCnt = 0; synced = false; } /** * Generate a new bit from the PRBS9 sequence. * * @return a bit from the PRBS9 sequence. */ bool generateBit() { bool result = ((state >> TAP_1) ^ (state >> TAP_2)) & 0x01; state = ((state << 1) | result) & MASK; return result; } /** * Syncronise the PRBS9 generator with an external stream of bits. * * @param bit: current bit of the external stream. * @return true when the PRBS9 state is syncronised with the bit stream. */ bool syncronize(const bool& bit) { if(synced) return true; bool result = (bit ^ (state >> TAP_1) ^ (state >> TAP_2)) & 1; state = ((state << 1) | bit) & MASK; syncCnt += 1; if(result) { syncCnt = 0; synced = false; } if(syncCnt >= LOCK_COUNT) { synced = true; } return synced; } /** * Validate the current bit of an external stream against the PRBS9 state * and advance the generator state by one step. To have meaningful results * the generator state has to be syncronised with the stream. * * @param bit: current bit of the external stream. * @return true if the bit from the PRBS9 matches the external one, false * otherwise. */ bool validateBit(const bool& bit) { if(synced == false) return false; return ((bit ^ generateBit()) == 0); } private: static constexpr uint16_t MASK = 0x1FF; static constexpr uint8_t TAP_1 = 8; static constexpr uint8_t TAP_2 = 4; static constexpr uint8_t LOCK_COUNT = 18; uint16_t state; uint8_t syncCnt; bool synced; }; } // namespace M17 #endif // M17PRBS_H