Fibonacci Linear Feedback Shift Register
[debian/gnuradio] / gnuradio-core / src / lib / general / gr_ofdm_qpsk_mapper.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2007 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <gr_ofdm_qpsk_mapper.h>
28 #include <gr_io_signature.h>
29 #include <stdexcept>
30 #include <string.h>
31
32 gr_ofdm_qpsk_mapper_sptr
33 gr_make_ofdm_qpsk_mapper (unsigned int msgq_limit, 
34                           unsigned int occupied_carriers, unsigned int fft_length)
35 {
36   return gr_ofdm_qpsk_mapper_sptr (new gr_ofdm_qpsk_mapper (msgq_limit, occupied_carriers, fft_length));
37 }
38
39 // Consumes 1 packet and produces as many OFDM symbols of fft_length to hold the full packet
40 gr_ofdm_qpsk_mapper::gr_ofdm_qpsk_mapper (unsigned int msgq_limit, 
41                                           unsigned int occupied_carriers, unsigned int fft_length)
42   : gr_sync_block ("ofdm_qpsk_mapper",
43                    gr_make_io_signature (0, 0, 0),
44                    gr_make_io_signature2 (1, 2, sizeof(gr_complex)*fft_length, sizeof(char))),
45     d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false),
46     d_occupied_carriers(occupied_carriers),
47     d_fft_length(fft_length),
48     d_bit_offset(0),
49     d_pending_flag(0)
50 {
51   if (!(d_occupied_carriers <= d_fft_length))
52     throw std::invalid_argument("gr_ofdm_qpsk_mapper: occupied carriers must be <= fft_length");
53 }
54
55 gr_ofdm_qpsk_mapper::~gr_ofdm_qpsk_mapper(void)
56 {
57 }
58
59 static gr_complex
60 randombit()
61 {
62   int r1 = rand()&1;
63   int r2 = rand()&1;
64   return gr_complex((0.707)*(1 - 2*r1),(0.707)*(1 - 2*r2));
65 }
66
67 int
68 gr_ofdm_qpsk_mapper::work(int noutput_items,
69                           gr_vector_const_void_star &input_items,
70                           gr_vector_void_star &output_items)
71 {
72   gr_complex *out = (gr_complex *)output_items[0];
73   
74   unsigned int i=0;
75   unsigned int unoccupied_carriers = d_fft_length - d_occupied_carriers;
76   unsigned int zeros_on_left = (unsigned)ceil(unoccupied_carriers/2.0);
77
78   //printf("OFDM QPSK Mapper:  ninput_items: %d   noutput_items: %d\n", ninput_items[0], noutput_items);
79
80   if(d_eof) {
81     return -1;
82   }
83   
84   if(!d_msg) {
85     d_msg = d_msgq->delete_head();         // block, waiting for a message
86     d_msg_offset = 0;
87     d_bit_offset = 0;
88     d_pending_flag = 1;                    // new packet, write start of packet flag
89     
90     if((d_msg->length() == 0) && (d_msg->type() == 1)) {
91       d_msg.reset();
92       return -1;                // We're done; no more messages coming.
93     }
94   }
95
96   char *out_flag = 0;
97   if(output_items.size() == 2)
98     out_flag = (char *) output_items[1];
99   
100
101   // Build a single symbol:
102   
103
104   // Initialize all bins to 0 to set unused carriers
105   memset(out, 0, d_fft_length*sizeof(gr_complex));
106   
107   i = 0;
108   while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) {
109     unsigned char bit0 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
110     d_bit_offset++;
111     
112     unsigned char bit1 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
113     d_bit_offset++;
114     
115     out[i + zeros_on_left] = gr_complex((0.707)*(1-2*(bit0)), (0.707)*(1-2*(bit1)) );
116     i++;
117     if(d_bit_offset == 8) {
118       d_bit_offset = 0;
119       d_msg_offset++;
120     }
121   }
122
123   // Ran out of data to put in symbol
124   if (d_msg_offset == d_msg->length()) {
125     while(i < d_occupied_carriers) {   // finish filling out the symbol
126       out[i + zeros_on_left] = randombit();
127       i++;
128     }
129
130     if (d_msg->type() == 1)             // type == 1 sets EOF
131       d_eof = true;
132     d_msg.reset();                      // finished packet, free message
133     assert(d_bit_offset == 0);
134   }
135
136   if (out_flag)
137     out_flag[0] = d_pending_flag;
138   d_pending_flag = 0;
139
140   return 1;  // produced symbol
141 }
142