⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pager_flex_sync.cc

📁 这是用python语言写的一个数字广播的信号处理工具包。利用它
💻 CC
字号:
/* * Copyright 2004,2006 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. */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <pager_flex_sync.h>#include <pageri_flex_modes.h>#include <pageri_bch3221.h>#include <pageri_util.h>#include <gr_io_signature.h>#include <gr_count_bits.h>pager_flex_sync_sptr pager_make_flex_sync(){    return pager_flex_sync_sptr(new pager_flex_sync());}// FLEX sync block takes input from sliced baseband stream [0-3] at specified // channel rate.  Symbol timing is established based on receiving one of the// defined FLEX protocol synchronization words.  The block outputs one FLEX frame// worth of bits on each output phase for the data portion of the frame. Unused phases// get all zeros, which are considered idle code words.pager_flex_sync::pager_flex_sync() :    gr_block ("flex_sync",    gr_make_io_signature (1, 1, sizeof(unsigned char)),    gr_make_io_signature (4, 4, sizeof(unsigned char))),    d_sync(10) // Fixed at 10 samples per baud (@ 1600 baud){    enter_idle();}void pager_flex_sync::forecast(int noutput_items, gr_vector_int &inputs_required){    // samples per bit X number of outputs needed    int items = noutput_items*d_spb;    for (unsigned int i = 0; i < inputs_required.size(); i++)        inputs_required[i] = items;}int pager_flex_sync::index_avg(int start, int end){    // modulo average    if (start < end)        return (end + start)/2;    else        return ((end + start)/2 + d_spb/2) % d_spb;}bool pager_flex_sync::test_sync(unsigned char sym){    // 64-bit FLEX sync code:    // AAAA:BBBBBBBB:CCCC    //    // Where BBBBBBBB is always 0xA6C6AAAA    // and AAAA^CCCC is 0xFFFF    //     // Specific values of AAAA determine what bps and encoding the    // packet is beyond the frame information word    //    // First we match on the marker field with a hamming distance < 4    // Then we match on the outer code with a hamming distance < 4    d_sync[d_index] = (d_sync[d_index] << 1) | (sym < 2);    gr_int64 val = d_sync[d_index];    gr_int32 marker = ((val & 0x0000FFFFFFFF0000ULL)) >> 16;    if (gr_count_bits32(marker^FLEX_SYNC_MARKER) < 4) {        gr_int32 code = ((val & 0xFFFF000000000000ULL) >> 32) |                         (val & 0x000000000000FFFFULL);        for (int i = 0; i < num_flex_modes; i++) {            if (gr_count_bits32(code^flex_modes[i].sync) < 4) {                d_mode = i;                return true;            }        }        // Marker received but doesn't match known codes        // All codes have high word inverted to low word        unsigned short high = (code & 0xFFFF0000) >> 16;        unsigned short low = code & 0x0000FFFF;        unsigned short syn = high^low;        if (syn == 0xFFFF)            fprintf(stderr, "Unknown sync code detected: %08X\n", code);    }    return false;}void pager_flex_sync::enter_idle(){    d_state = ST_IDLE;    d_index = 0;    d_start = 0;    d_center = 0;    d_end = 0;    d_count = 0;    d_mode = 0;    d_baudrate = 1600;    d_levels = 2;    d_spb = 16000/d_baudrate;    d_bit_a = 0;    d_bit_b = 0;    d_bit_c = 0;    d_bit_d = 0;    d_hibit = false;    fflush(stdout);}void pager_flex_sync::enter_syncing(){    d_start = d_index;    d_state = ST_SYNCING;}void pager_flex_sync::enter_sync1(){    d_state = ST_SYNC1;    d_end = d_index;    d_center = index_avg(d_start, d_end); // Center of goodness    d_count = 0;}void pager_flex_sync::enter_sync2(){    d_state = ST_SYNC2;    d_count = 0;    d_baudrate = flex_modes[d_mode].baud;    d_levels = flex_modes[d_mode].levels;    d_spb = 16000/d_baudrate;    if (d_baudrate == 3200) {        // Oversampling buffer just got halved        d_center = d_center/2;	// We're here at the center of a 1600 baud bit	// So this hack puts the index and bit counter	// in the right place for 3200 bps.        d_index = d_index/2-d_spb/2;         	d_count = -1;                    }				     }void pager_flex_sync::enter_data(){    d_state = ST_DATA;    d_count = 0;}void pager_flex_sync::parse_fiw(){    // Nothing is done with these now, but these will end up getting    // passed as metadata when mblocks are available    // Bits 31-28 are frame number related, but unknown function    // This might be a checksum    d_unknown2 = pageri_reverse_bits8((d_fiw >> 24) & 0xF0);	    // Cycle is bits 27-24, reversed    d_cycle = pageri_reverse_bits8((d_fiw >> 20) & 0xF0);    // Frame is bits 23-17, reversed    d_frame = pageri_reverse_bits8((d_fiw >> 16) & 0xFE);    // Bits 16-11 are some sort of marker, usually identical across    // many frames but sometimes changes between frames or modes    d_unknown1 = (d_fiw >> 11) & 0x3F;    //printf("CYC:%02i FRM:%03i\n", d_cycle, d_frame);}int pager_flex_sync::output_symbol(unsigned char sym){    // Here is where we output a 1 or 0 on each phase according    // to current FLEX mode and symbol value.  Unassigned phases    // are zero from the enter_idle() initialization.    //    // FLEX can transmit the data portion of the frame at either    // 1600 bps or 3200 bps, and can use either two- or four-level    // FSK encoding.    //    // At 1600 bps, 2-level, a single "phase" is transmitted with bit    // value '0' using level '3' and bit value '1' using level '0'.    //    // At 1600 bps, 4-level, a second "phase" is transmitted, and the     // di-bits are encoded with a gray code:    //    // Symbol	Phase 1  Phase 2    // ------   -------  -------    //   0         1        1    //   1         1        0    //   2         0        0    //   3         0        1    //    // At 1600 bps, 4-level, these are called PHASE A and PHASE B.    //    // At 3200 bps, the same 1 or 2 bit encoding occurs, except that    // additionally two streams are interleaved on alternating symbols.    // Thus, PHASE A (and PHASE B if 4-level) are decoded on one symbol,    // then PHASE C (and PHASE D if 4-level) are decoded on the next.        int bits = 0;        if (d_baudrate == 1600) {	d_bit_a = (sym < 2);	if (d_levels == 4)	    d_bit_b = (sym == 0) || (sym == 3);	*d_phase_a++ = d_bit_a;	*d_phase_b++ = d_bit_b;	*d_phase_c++ = d_bit_c;	*d_phase_d++ = d_bit_d;	bits++;    }    else {	if (!d_hibit) {	    d_bit_a = (sym < 2);	    if (d_levels == 4)		d_bit_b = (sym == 0) || (sym == 3);	    d_hibit = true;	}	else {	    d_bit_c = (sym < 2);	    if (d_levels == 4)		d_bit_d = (sym == 0) || (sym == 3);	    d_hibit = false;	    *d_phase_a++ = d_bit_a;	    *d_phase_b++ = d_bit_b;	    *d_phase_c++ = d_bit_c;	    *d_phase_d++ = d_bit_d;	    bits++;	}    }    return bits;}int pager_flex_sync::general_work(int noutput_items,    gr_vector_int &ninput_items,    gr_vector_const_void_star &input_items,    gr_vector_void_star &output_items){    const unsigned char *in = (const unsigned char *)input_items[0];    d_phase_a = (unsigned char *)output_items[0];    d_phase_b = (unsigned char *)output_items[1];    d_phase_c = (unsigned char *)output_items[2];    d_phase_d = (unsigned char *)output_items[3];    int i = 0, j = 0;    int ninputs = ninput_items[0];    while (i < ninputs && j < noutput_items) {        unsigned char sym = *in++; i++;        d_index = ++d_index % d_spb;            switch (d_state) {            case ST_IDLE:		// Continually compare the received symbol stream		// against the known FLEX sync words.                if (test_sync(sym))                    enter_syncing();                break;                case ST_SYNCING:		// Wait until we stop seeing sync, then calculate		// the center of the bit period (d_center)                if (!test_sync(sym))                    enter_sync1();                break;                case ST_SYNC1:		// Skip 16 bits of dotting, then accumulate 32 bits		// of Frame Information Word.                if (d_index == d_center) {		    d_fiw = (d_fiw << 1) | (sym > 1);                    if (++d_count == 48) {			// FIW is accumulated, call BCH to error correct it			pageri_bch3221(d_fiw);			parse_fiw();                        enter_sync2();  		    }                }                break;                case ST_SYNC2:		// This part and the remainder of the frame are transmitted		// at either 1600 bps or 3200 bps based on the received		// FLEX sync word. The second SYNC header is 25ms of idle bits		// at either speed.                if (d_index == d_center) {                    // Skip 25 ms = 40 bits @ 1600 bps, 80 @ 3200 bps                    if (++d_count == d_baudrate/40)                        enter_data();                }                break;                case ST_DATA:		// The data portion of the frame is 1760 ms long at either 		// baudrate.  This is 2816 bits @ 1600 bps and 5632 bits @ 3200 bps.		// The output_symbol() routine decodes and doles out the bits		// to each of the four transmitted phases of FLEX interleaved codes.                if (d_index == d_center) {		    j += output_symbol(sym);		                        if (++d_count == d_baudrate*1760/1000)                        enter_idle();		}                break;            default:                assert(0); // memory corruption of d_state if ever gets here                break;        }    }    consume_each(i);    return j;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -