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>
32 gr_ofdm_qam_mapper_sptr
33 gr_make_ofdm_qam_mapper (unsigned int msgq_limit,
34 unsigned int occupied_carriers, unsigned int fft_length,
37 return gr_ofdm_qam_mapper_sptr (new gr_ofdm_qam_mapper (msgq_limit, occupied_carriers, fft_length, m));
40 // Consumes 1 packet and produces as many OFDM symbols of fft_length to hold the full packet
41 gr_ofdm_qam_mapper::gr_ofdm_qam_mapper (unsigned int msgq_limit,
42 unsigned int occupied_carriers, unsigned int fft_length,
44 : gr_sync_block ("ofdm_qam_mapper",
45 gr_make_io_signature (0, 0, 0),
46 gr_make_io_signature2 (1, 2, sizeof(gr_complex)*fft_length, sizeof(char))),
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),
54 if (!(d_occupied_carriers <= d_fft_length))
55 throw std::invalid_argument("gr_ofdm_qam_mapper: occupied carriers must be <= fft_length");
75 throw std::invalid_argument("Order M must be [2, 4, 16, 64, 256]");
80 gr_ofdm_qam_mapper::~gr_ofdm_qam_mapper(void)
84 void gr_ofdm_qam_mapper::make_constellation()
86 int i = 0, j = 0, ii = 0, jj = 0;
87 // number of bits/symbol (log2(M))
88 int k = (int)(log10(d_mod_order) / log10(2.0));
93 std::vector<int> bits_i, bits_q;
97 int ll = bits_i.size();
99 for(i=0; i < d_mod_order; i++) {
100 a = (i & (0x01 << (k-1))) >> (k-1);
101 b = (i & (0x01 << (k-2))) >> (k-2);
102 for(j=2; j < k; j+=2) {
103 bits_i.push_back( (i & (0x01 << (k-j-1))) >> (k-j-1));
104 bits_q.push_back( (i & (0x01 << (k-(j+1)-1))) >> (k-(j+1)-1));
109 for(ii = 0; ii < ll; ii++) {
111 for(jj = 0; jj < (ll-ii); jj++) {
112 rr = abs(bits_i[jj] - rr);
114 ss += rr * pow(2.0, ii+1.0);
116 re = (2.0*a-1.0)*(ss+1.0);
120 for(ii = 0; ii < ll; ii++) {
122 for(jj = 0; jj < (ll-ii); jj++) {
123 rr = abs(bits_q[jj] - rr);
125 ss += rr*pow(2.0, ii+1.0);
127 im = (2.0*b-1.0)*(ss+1.0);
129 a = std::max(re, im);
133 d_constellation_map.push_back(gr_complex(re, im));
136 d_constellation_map[0] = gr_complex(-3, -3);
137 d_constellation_map[1] = gr_complex(-3, -1);
138 d_constellation_map[2] = gr_complex(-3, 1);
139 d_constellation_map[3] = gr_complex(-3, 3);
140 d_constellation_map[4] = gr_complex(-1, -3);
141 d_constellation_map[5] = gr_complex(-1, -1);
142 d_constellation_map[6] = gr_complex(-1, 1);
143 d_constellation_map[7] = gr_complex(-1, 3);
144 d_constellation_map[8] = gr_complex(1, -3);
145 d_constellation_map[9] = gr_complex(1, -1);
146 d_constellation_map[10] = gr_complex(1, 1);
147 d_constellation_map[11] = gr_complex(1, 3);
148 d_constellation_map[12] = gr_complex(3, -3);
149 d_constellation_map[13] = gr_complex(3, -1);
150 d_constellation_map[14] = gr_complex(3, 1);
151 d_constellation_map[15] = gr_complex(3, 3);
153 coeff = sqrt(31.0)/2.0;
154 for(i = 0; i < static_cast<int>(d_constellation_map.size()); i++) {
155 d_constellation_map[i] /= coeff;
156 printf("const[%d]: %f + j%f\n", i, d_constellation_map[i].real(), d_constellation_map[i].imag());
165 return (float)(-1 + 2*r);
170 gr_ofdm_qam_mapper::work(int noutput_items,
171 gr_vector_const_void_star &input_items,
172 gr_vector_void_star &output_items)
174 gr_complex *out = (gr_complex *)output_items[0];
177 unsigned int unoccupied_carriers = d_fft_length - d_occupied_carriers;
178 unsigned int zeros_on_left = (unsigned)ceil(unoccupied_carriers/2.0);
180 //printf("OFDM QAM Mapper: ninput_items: %d noutput_items: %d\n", ninput_items[0], noutput_items);
187 d_msg = d_msgq->delete_head(); // block, waiting for a message
190 d_pending_flag = 1; // new packet, write start of packet flag
192 if((d_msg->length() == 0) && (d_msg->type() == 1)) {
194 return -1; // We're done; no more messages coming.
199 if(output_items.size() == 2)
200 out_flag = (char *) output_items[1];
203 // Build a single symbol:
206 // Initialize all bins to 0 to set unused carriers
207 memset(out, 0, d_fft_length*sizeof(gr_complex));
210 while((d_msg_offset < d_msg->length()) && (i < d_occupied_carriers)) {
211 unsigned char bit0 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
214 unsigned char bit1 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
217 unsigned char bit2 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
220 unsigned char bit3 = (d_msg->msg()[d_msg_offset] >> (d_bit_offset)) & 0x01;
223 unsigned char bit = (bit0 << 3) | (bit1 << 2) | (bit2 << 1) | (bit3 << 0);
225 out[i + zeros_on_left] = d_constellation_map[bit];
227 if(d_bit_offset == 8) {
233 // Ran out of data to put in symbol
234 if (d_msg_offset == d_msg->length()) {
235 while(i < d_occupied_carriers) { // finish filling out the symbol
236 out[i + zeros_on_left] = d_constellation_map[rand() & 0x0F];
240 if (d_msg->type() == 1) // type == 1 sets EOF
242 d_msg.reset(); // finished packet, free message
243 assert(d_bit_offset == 0);
247 out_flag[0] = d_pending_flag;
250 return 1; // produced symbol