Merging OFDM features branch r5661:5759 into trunk. OFDM works over the air with...
[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 2, 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
31 gr_ofdm_qpsk_mapper_sptr
32 gr_make_ofdm_qpsk_mapper (unsigned int msgq_limit, 
33                           unsigned int occupied_carriers, unsigned int fft_length)
34 {
35   return gr_ofdm_qpsk_mapper_sptr (new gr_ofdm_qpsk_mapper (msgq_limit, occupied_carriers, fft_length));
36 }
37
38 // Consumes 1 packet and produces as many OFDM symbols of fft_length to hold the full packet
39 gr_ofdm_qpsk_mapper::gr_ofdm_qpsk_mapper (unsigned int msgq_limit, 
40                                           unsigned int occupied_carriers, unsigned int fft_length)
41   : gr_sync_block ("ofdm_qpsk_mapper",
42                    gr_make_io_signature (0, 0, 0),
43                    gr_make_io_signature2 (1, 2, sizeof(gr_complex)*fft_length, sizeof(char))),
44     d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false),
45     d_occupied_carriers(occupied_carriers),
46     d_fft_length(fft_length),
47     d_bit_offset(0),
48     d_pending_flag(0)
49 {
50   if (!(d_occupied_carriers <= d_fft_length))
51     throw std::invalid_argument("gr_ofdm_qpsk_mapper: occupied carriers must be <= fft_length");
52 }
53
54 gr_ofdm_qpsk_mapper::~gr_ofdm_qpsk_mapper(void)
55 {
56 }
57
58 static gr_complex
59 randombit()
60 {
61   int r1 = rand()&1;
62   int r2 = rand()&1;
63   return gr_complex((0.707)*(-1 + 2*r1),(0.707)*(-1 + 2*r2));
64 }
65
66 int
67 gr_ofdm_qpsk_mapper::work(int noutput_items,
68                           gr_vector_const_void_star &input_items,
69                           gr_vector_void_star &output_items)
70 {
71   gr_complex *out = (gr_complex *)output_items[0];
72   
73   unsigned int i=0;
74   unsigned int unoccupied_carriers = d_fft_length - d_occupied_carriers;
75   unsigned int zeros_on_left = (unsigned)ceil(unoccupied_carriers/2.0);
76
77   //printf("OFDM QPSK Mapper:  ninput_items: %d   noutput_items: %d\n", ninput_items[0], noutput_items);
78
79   if(d_eof) {
80     return -1;
81   }
82   
83   if(!d_msg) {
84     d_msg = d_msgq->delete_head();         // block, waiting for a message
85     d_msg_offset = 0;
86     d_bit_offset = 0;
87     d_pending_flag = 1;                    // new packet, write start of packet flag
88     
89     if((d_msg->length() == 0) && (d_msg->type() == 1)) {
90       d_msg.reset();
91       return -1;                // We're done; no more messages coming.
92     }
93   }
94
95   char *out_flag = 0;
96   if(output_items.size() == 2)
97     out_flag = (char *) output_items[1];
98   
99
100   // Build a single symbol:
101   
102
103   // Initialize all bins to 0 to set unused carriers
104   memset(out, 0, d_fft_length*sizeof(gr_complex));
105   
106   i = 0;
107   while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) {
108     unsigned char bit0 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
109     d_bit_offset++;
110     
111     unsigned char bit1 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
112     d_bit_offset++;
113     
114     out[i + zeros_on_left] = gr_complex((0.707)*(-1+2*(bit0)), (0.707)*(-1+2*(bit1)) );
115     i++;
116     if(d_bit_offset == 8) {
117       d_bit_offset = 0;
118       d_msg_offset++;
119     }
120   }
121
122   // Ran out of data to put in symbol
123   if (d_msg_offset == d_msg->length()) {
124     while(i < d_occupied_carriers) {   // finish filling out the symbol
125       out[i + zeros_on_left] = randombit();
126       i++;
127     }
128
129     if (d_msg->type() == 1)             // type == 1 sets EOF
130       d_eof = true;
131     d_msg.reset();                      // finished packet, free message
132     assert(d_bit_offset == 0);
133   }
134
135   if (out_flag)
136     out_flag[0] = d_pending_flag;
137   d_pending_flag = 0;
138
139   return 1;  // produced symbol
140 }
141