Merging ofdm2 branch -r7047:7321 into trunk. This updates the OFDM code to hier_block...
[debian/gnuradio] / gnuradio-core / src / lib / general / gr_ofdm_mapper_bcv.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006,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
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <gr_ofdm_mapper_bcv.h>
29 #include <gr_io_signature.h>
30 #include <stdexcept>
31
32 gr_ofdm_mapper_bcv_sptr
33 gr_make_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation, unsigned int msgq_limit, 
34                          unsigned int occupied_carriers, unsigned int fft_length)
35 {
36   return gr_ofdm_mapper_bcv_sptr (new gr_ofdm_mapper_bcv (constellation, msgq_limit, 
37                                                           occupied_carriers, fft_length));
38 }
39
40 // Consumes 1 packet and produces as many OFDM symbols of fft_length to hold the full packet
41 gr_ofdm_mapper_bcv::gr_ofdm_mapper_bcv (const std::vector<gr_complex> &constellation, unsigned int msgq_limit, 
42                                         unsigned int occupied_carriers, unsigned int fft_length)
43   : gr_sync_block ("ofdm_mapper_bcv",
44                    gr_make_io_signature (0, 0, 0),
45                    gr_make_io_signature2 (1, 2, sizeof(gr_complex)*fft_length, sizeof(char))),
46     d_constellation(constellation),
47     d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false),
48     d_occupied_carriers(occupied_carriers),
49     d_fft_length(fft_length),
50     d_bit_offset(0),
51     d_pending_flag(0),
52     d_resid(0),
53     d_nresid(0)
54 {
55   if (!(d_occupied_carriers <= d_fft_length))
56     throw std::invalid_argument("gr_ofdm_mapper_bcv: occupied carriers must be <= fft_length");
57   
58   d_nbits = (unsigned long)ceil(log10(d_constellation.size()) / log10(2.0));
59 }
60
61 gr_ofdm_mapper_bcv::~gr_ofdm_mapper_bcv(void)
62 {
63 }
64
65 int gr_ofdm_mapper_bcv::randsym()
66 {
67   return (rand() % d_constellation.size());
68 }
69
70 int
71 gr_ofdm_mapper_bcv::work(int noutput_items,
72                           gr_vector_const_void_star &input_items,
73                           gr_vector_void_star &output_items)
74 {
75   gr_complex *out = (gr_complex *)output_items[0];
76   
77   unsigned int i=0;
78   unsigned int unoccupied_carriers = d_fft_length - d_occupied_carriers;
79   unsigned int zeros_on_left = (unsigned)ceil(unoccupied_carriers/2.0);
80
81   //printf("OFDM BPSK Mapper:  ninput_items: %d   noutput_items: %d\n", ninput_items[0], noutput_items);
82
83   if(d_eof) {
84     return -1;
85   }
86   
87   if(!d_msg) {
88     d_msg = d_msgq->delete_head();         // block, waiting for a message
89     d_msg_offset = 0;
90     d_bit_offset = 0;
91     d_pending_flag = 1;                    // new packet, write start of packet flag
92     
93     if((d_msg->length() == 0) && (d_msg->type() == 1)) {
94       d_msg.reset();
95       return -1;                // We're done; no more messages coming.
96     }
97   }
98
99   char *out_flag = 0;
100   if(output_items.size() == 2)
101     out_flag = (char *) output_items[1];
102   
103
104   // Build a single symbol:
105   // Initialize all bins to 0 to set unused carriers
106   memset(out, 0, d_fft_length*sizeof(gr_complex));
107   
108   i = 0;
109   unsigned char bits = 0;
110   while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) {
111     
112     // need new data to process
113     if(d_bit_offset == 0) {
114       d_msgbytes = d_msg->msg()[d_msg_offset];
115       //printf("mod message byte: %x\n", d_msgbytes);
116     }
117
118     if(d_nresid > 0) {
119       d_resid |= (((1 << d_nresid)-1) & d_msgbytes) << (d_nbits - d_nresid);
120       bits = d_resid;
121
122       out[i + zeros_on_left] = d_constellation[bits];
123       i++;
124
125       d_bit_offset += d_nresid;
126       d_nresid = 0;
127       d_resid = 0;
128       //printf("mod bit(r): %x   resid: %x   nresid: %d    bit_offset: %d\n", 
129       //     bits, d_resid, d_nresid, d_bit_offset);
130     }
131     else {
132       if((8 - d_bit_offset) >= d_nbits) {
133         bits = ((1 << d_nbits)-1) & (d_msgbytes >> d_bit_offset);
134         d_bit_offset += d_nbits;
135         
136         out[i + zeros_on_left] = d_constellation[bits];
137         i++;
138         
139         /*
140         printf("mod bit: %x  out: %.4f + j%.4f    resid: %x   nresid: %d    bit_offset: %d\n", 
141                bits, out[i-1 + zeros_on_left].real(), out[i-1 + zeros_on_left].imag(), 
142                d_resid, d_nresid, d_bit_offset);
143         */
144       }
145       else {
146         unsigned int extra = 8-d_bit_offset;
147         d_resid = ((1 << extra)-1) & (d_msgbytes >> d_bit_offset);
148         d_bit_offset += extra;
149         d_nresid = d_nbits - extra;
150       }
151       
152     }
153             
154     if(d_bit_offset == 8) {
155       d_bit_offset = 0;
156       d_msg_offset++;
157     }
158   }
159
160   // Ran out of data to put in symbol
161   if (d_msg_offset == d_msg->length()) {
162     if(d_nresid > 0) {
163       d_resid |= 0x00;
164       bits = d_resid;
165       d_nresid = 0;
166       d_resid = 0;
167     }
168
169     while(i < d_occupied_carriers) {   // finish filling out the symbol
170       out[i + zeros_on_left] = d_constellation[randsym()];
171       i++;
172     }
173
174     if (d_msg->type() == 1)             // type == 1 sets EOF
175       d_eof = true;
176     d_msg.reset();                      // finished packet, free message
177     assert(d_bit_offset == 0);
178   }
179
180   if (out_flag)
181     out_flag[0] = d_pending_flag;
182   d_pending_flag = 0;
183
184   return 1;  // produced symbol
185 }