3 * Copyright 2007 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
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)
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.
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.
27 #include <gr_ofdm_qam_mapper.h>
28 #include <gr_io_signature.h>
31 gr_ofdm_qam_mapper_sptr
32 gr_make_ofdm_qam_mapper (unsigned int msgq_limit,
33 unsigned int occupied_carriers, unsigned int fft_length,
36 return gr_ofdm_qam_mapper_sptr (new gr_ofdm_qam_mapper (msgq_limit, occupied_carriers, fft_length, m));
39 // Consumes 1 packet and produces as many OFDM symbols of fft_length to hold the full packet
40 gr_ofdm_qam_mapper::gr_ofdm_qam_mapper (unsigned int msgq_limit,
41 unsigned int occupied_carriers, unsigned int fft_length,
43 : gr_sync_block ("ofdm_qam_mapper",
44 gr_make_io_signature (0, 0, 0),
45 gr_make_io_signature2 (1, 2, sizeof(gr_complex)*fft_length, sizeof(char))),
46 d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false),
47 d_occupied_carriers(occupied_carriers),
48 d_fft_length(fft_length),
53 if (!(d_occupied_carriers <= d_fft_length))
54 throw std::invalid_argument("gr_ofdm_qam_mapper: occupied carriers must be <= fft_length");
74 throw std::invalid_argument("Order M must be [2, 4, 16, 64, 256]");
79 gr_ofdm_qam_mapper::~gr_ofdm_qam_mapper(void)
83 void gr_ofdm_qam_mapper::make_constellation()
85 int i = 0, j = 0, ii = 0, jj = 0;
86 // number of bits/symbol (log2(M))
87 int k = (int)(log10(d_mod_order) / log10(2.0));
92 std::vector<int> bits_i, bits_q;
96 int ll = bits_i.size();
98 for(i=0; i < d_mod_order; i++) {
99 a = (i & (0x01 << (k-1))) >> (k-1);
100 b = (i & (0x01 << (k-2))) >> (k-2);
101 for(j=2; j < k; j+=2) {
102 bits_i.push_back( (i & (0x01 << (k-j-1))) >> (k-j-1));
103 bits_q.push_back( (i & (0x01 << (k-(j+1)-1))) >> (k-(j+1)-1));
108 for(ii = 0; ii < ll; ii++) {
110 for(jj = 0; jj < (ll-ii); jj++) {
111 rr = abs(bits_i[jj] - rr);
113 ss += rr * pow(2.0, ii+1.0);
115 re = (2.0*a-1.0)*(ss+1.0);
119 for(ii = 0; ii < ll; ii++) {
121 for(jj = 0; jj < (ll-ii); jj++) {
122 rr = abs(bits_q[jj] - rr);
124 ss += rr*pow(2.0, ii+1.0);
126 im = (2.0*b-1.0)*(ss+1.0);
128 a = std::max(re, im);
132 d_constellation_map.push_back(gr_complex(re, im));
135 d_constellation_map[0] = gr_complex(-3, -3);
136 d_constellation_map[1] = gr_complex(-3, -1);
137 d_constellation_map[2] = gr_complex(-3, 1);
138 d_constellation_map[3] = gr_complex(-3, 3);
139 d_constellation_map[4] = gr_complex(-1, -3);
140 d_constellation_map[5] = gr_complex(-1, -1);
141 d_constellation_map[6] = gr_complex(-1, 1);
142 d_constellation_map[7] = gr_complex(-1, 3);
143 d_constellation_map[8] = gr_complex(1, -3);
144 d_constellation_map[9] = gr_complex(1, -1);
145 d_constellation_map[10] = gr_complex(1, 1);
146 d_constellation_map[11] = gr_complex(1, 3);
147 d_constellation_map[12] = gr_complex(3, -3);
148 d_constellation_map[13] = gr_complex(3, -1);
149 d_constellation_map[14] = gr_complex(3, 1);
150 d_constellation_map[15] = gr_complex(3, 3);
152 coeff = sqrt(31.0)/2.0;
153 for(i = 0; i < d_constellation_map.size(); i++) {
154 d_constellation_map[i] /= coeff;
155 printf("const[%d]: %f + j%f\n", i, d_constellation_map[i].real(), d_constellation_map[i].imag());
163 return (float)(-1 + 2*r);
167 gr_ofdm_qam_mapper::work(int noutput_items,
168 gr_vector_const_void_star &input_items,
169 gr_vector_void_star &output_items)
171 gr_complex *out = (gr_complex *)output_items[0];
174 unsigned int unoccupied_carriers = d_fft_length - d_occupied_carriers;
175 unsigned int zeros_on_left = (unsigned)ceil(unoccupied_carriers/2.0);
177 //printf("OFDM QAM Mapper: ninput_items: %d noutput_items: %d\n", ninput_items[0], noutput_items);
184 d_msg = d_msgq->delete_head(); // block, waiting for a message
187 d_pending_flag = 1; // new packet, write start of packet flag
189 if((d_msg->length() == 0) && (d_msg->type() == 1)) {
191 return -1; // We're done; no more messages coming.
196 if(output_items.size() == 2)
197 out_flag = (char *) output_items[1];
200 // Build a single symbol:
203 // Initialize all bins to 0 to set unused carriers
204 memset(out, 0, d_fft_length*sizeof(gr_complex));
207 while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) {
208 unsigned char bit0 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
211 unsigned char bit1 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
214 unsigned char bit2 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
217 unsigned char bit3 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
220 unsigned char bit = (bit0 << 3) | (bit1 << 2) | (bit2 << 1) | (bit3 << 0);
222 out[i + zeros_on_left] = d_constellation_map[bit];
224 if(d_bit_offset == 8) {
230 // Ran out of data to put in symbol
231 if (d_msg_offset == d_msg->length()) {
232 while(i < d_occupied_carriers) { // finish filling out the symbol
233 out[i + zeros_on_left] = d_constellation_map[rand() & 0x0F];
237 if (d_msg->type() == 1) // type == 1 sets EOF
239 d_msg.reset(); // finished packet, free message
240 assert(d_bit_offset == 0);
244 out_flag[0] = d_pending_flag;
247 return 1; // produced symbol