/* -*- c++ -*- */ /* Copyright 2015-2016 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio 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, or (at your option) * any later version. * * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ #ifndef INCLUDED_DIGITAL_HEADER_FORMAT_DEFAULT_H #define INCLUDED_DIGITAL_HEADER_FORMAT_DEFAULT_H #include <pmt/pmt.h> #include <gnuradio/digital/api.h> #include <gnuradio/digital/header_format_base.h> #include <gnuradio/digital/header_buffer.h> #include <gnuradio/logger.h> #include <boost/enable_shared_from_this.hpp> namespace gr { namespace digital { /*! * \brief Default header formatter for PDU formatting. * \ingroup packet_operators_blk * * \details * Used to handle the default packet header. * * See the parent class header_format_base for details of how * these classes operate. * * The default header created in this base class consists of an * access code and the packet length. The length is encoded as a * 16-bit value repeated twice: * * \verbatim | access code | hdr | payload | \endverbatim * * Where the access code is <= 64 bits and hdr is: * * \verbatim | 0 -- 15 | 16 -- 31 | | pkt len | pkt len | \endverbatim * * The access code and header are formatted for network byte order. * * This header generator does not calculate or append a CRC to the * packet. Use the CRC32 Async block for that before adding the * header. The header's length will then measure the payload plus * the CRC length (4 bytes for a CRC32). * * The default header parser produces a PMT dictionary that * contains the following keys. All formatter blocks MUST produce * these two values in any dictionary. * * \li "payload symbols": the number of symbols in the * payload. The payload decoder will have to know how this relates * to the number of bits received. This block knows nothing about * the payload modulation or the number of bits/symbol. Use the * gr::digital::header_format_counter for that purpose. * * \sa header_format_counter * \sa header_format_crc * \sa header_format_ofdm */ class DIGITAL_API header_format_default : public header_format_base { public: header_format_default(const std::string &access_code, int threshold, int bps); virtual ~header_format_default(); /*! * Creates a header from the access code and packet length and * creates an output header as a PMT vector in the form: * * \verbatim | access code | pkt len | pkt len | \endverbatim * * \param nbytes_in The length (in bytes) of the \p input payload * \param input An array of unsigned chars of the packet payload * \param output A pmt::u8vector with the new header prepended * onto the input data. * \param info A pmt::dict containing meta data and info about * the PDU (generally from the metadata portion of the * input PDU). Data can be extracted from this for the * header formatting or inserted. */ virtual bool format(int nbytes_in, const unsigned char *input, pmt::pmt_t &output, pmt::pmt_t &info); /*! * Parses a header of the form: * * \verbatim | access code | pkt len | pkt len | payload | \endverbatim * * This is implemented as a state machine that starts off * searching for the access code. Once found, the access code is * used to find the start of the packet and the following * header. This default header encodes the length of the payload * a 16 bit integer twice. The state machine finds the header * and checks that both payload length values are the same. It * then goes into its final state that reads in the payload * (based on the payload length) and produces a payload as a PMT * u8 vector of packed bytes. * * \param nbits_in The number of bits in the input array. * \param input The input as hard decision bits. * \param info A vector of pmt::dicts to hold any meta data or * info about the PDU. When parsing the header, the * formatter can add info from the header into this dict. * Each packet has a single PMT dictionary of info, so * the vector length is the number of packets received * extracted during one call to this parser function. * \param nbits_processed Number of input bits actually * processed; If all goes well, this is nbits_in. A * premature return after a bad header could be less than * this. */ virtual bool parse(int nbits_in, const unsigned char *input, std::vector<pmt::pmt_t> &info, int &nbits_processed); /*! * Returns the length of the formatted header in bits. */ virtual size_t header_nbits() const; /*! * Updates the access code. Must be a string of 1's and 0's and * <= 64 bits. */ bool set_access_code(const std::string &access_code); /*! * Returns the formatted access code as a 64-bit register. */ unsigned long long access_code() const; /*! * Sets the threshold for number of access code bits can be in * error before detection. Defaults to 0. */ void set_threshold(unsigned int thresh=0); /*! * Returns threshold value for access code detection. */ unsigned int threshold() const; /*! * Factory to create an async packet header formatter; returns * an sptr to the object. * * \param access_code An access code that is used to find and * synchronize the start of a packet. Used in the parser and in * other blocks like a corr_est block that helps trigger the * receiver. Can be up to 64-bits long. * \param threshold How many bits can be wrong in the access * code and still count as correct. * \param bps The number of bits/second used in the payload's * modulator. */ static sptr make(const std::string &access_code, int threshold, int bps = 1); protected: uint64_t d_access_code; //!< register to hold the access code size_t d_access_code_len; //!< length in bits of the access code uint16_t d_bps; //!< bits/sec of payload modulation unsigned long long d_data_reg; //!< used to look for access_code unsigned long long d_mask; /*!< masks access_code bits (top N bits are set where N is the number of bits in the access code) */ unsigned int d_threshold; //!< how many bits may be wrong in sync vector int d_pkt_len; //!< Length of the packet to put into the output buffer int d_pkt_count; //!< Number of bytes bits already received int d_nbits; //!< num bits processed since reset //! Access code found, start getting the header virtual void enter_have_sync(); //! Header found, setup for pulling in the hard decision bits virtual void enter_have_header(int payload_len); //! Verify that the header is valid virtual bool header_ok(); /*! Get info from the header; return payload length and package * rest of data in d_info dictionary. */ virtual int header_payload(); }; } // namespace digital } // namespace gr #endif /* INCLUDED_DIGITAL_HEADER_FORMAT_DEFAULT_H */