Merging OFDM features branch r5661:5759 into trunk. OFDM works over the air with...
[debian/gnuradio] / gnuradio-core / src / lib / general / gr_ofdm_bpsk_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_bpsk_mapper.h>
28 #include <gr_io_signature.h>
29 #include <stdexcept>
30
31 gr_ofdm_bpsk_mapper_sptr
32 gr_make_ofdm_bpsk_mapper (unsigned int msgq_limit, 
33                           unsigned int occupied_carriers, unsigned int fft_length)
34 {
35   return gr_ofdm_bpsk_mapper_sptr (new gr_ofdm_bpsk_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_bpsk_mapper::gr_ofdm_bpsk_mapper (unsigned int msgq_limit, 
40                                           unsigned int occupied_carriers, unsigned int fft_length)
41   : gr_sync_block ("ofdm_bpsk_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_bpsk_mapper: occupied carriers must be <= fft_length");
52 }
53
54 gr_ofdm_bpsk_mapper::~gr_ofdm_bpsk_mapper(void)
55 {
56 }
57
58 static float
59 randombit()
60 {
61   int r = rand()&1;
62   return (float)(-1 + 2*r);
63 }
64
65 int
66 gr_ofdm_bpsk_mapper::work(int noutput_items,
67                           gr_vector_const_void_star &input_items,
68                           gr_vector_void_star &output_items)
69 {
70   gr_complex *out = (gr_complex *)output_items[0];
71   
72   unsigned int i=0;
73   unsigned int unoccupied_carriers = d_fft_length - d_occupied_carriers;
74   unsigned int zeros_on_left = (unsigned)ceil(unoccupied_carriers/2.0);
75
76   //printf("OFDM BPSK Mapper:  ninput_items: %d   noutput_items: %d\n", ninput_items[0], noutput_items);
77
78   if(d_eof) {
79     return -1;
80   }
81   
82   if(!d_msg) {
83     d_msg = d_msgq->delete_head();         // block, waiting for a message
84     d_msg_offset = 0;
85     d_bit_offset = 0;
86     d_pending_flag = 1;                    // new packet, write start of packet flag
87     
88     if((d_msg->length() == 0) && (d_msg->type() == 1)) {
89       d_msg.reset();
90       return -1;                // We're done; no more messages coming.
91     }
92   }
93
94   char *out_flag = 0;
95   if(output_items.size() == 2)
96     out_flag = (char *) output_items[1];
97   
98
99   // Build a single symbol:
100   
101
102   // Initialize all bins to 0 to set unused carriers
103   memset(out, 0, d_fft_length*sizeof(gr_complex));
104   
105   i = 0;
106   while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) {
107     unsigned char bit = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
108     out[i + zeros_on_left] = gr_complex(-1+2*(bit));
109     i++;
110     d_bit_offset++;
111     if(d_bit_offset == 8) {
112       d_bit_offset = 0;
113       d_msg_offset++;
114     }
115   }
116
117   // Ran out of data to put in symbol
118   if (d_msg_offset == d_msg->length()) {
119     while(i < d_occupied_carriers) {   // finish filling out the symbol
120       out[i + zeros_on_left] = gr_complex(randombit(),0);
121       i++;
122     }
123
124     if (d_msg->type() == 1)             // type == 1 sets EOF
125       d_eof = true;
126     d_msg.reset();                      // finished packet, free message
127     assert(d_bit_offset == 0);
128   }
129
130   if (out_flag)
131     out_flag[0] = d_pending_flag;
132   d_pending_flag = 0;
133
134   return 1;  // produced symbol
135 }
136