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_frame_sink.h>
28 #include <gr_io_signature.h>
35 gr_ofdm_frame_sink::enter_search()
38 fprintf(stderr, "@ enter_search\n");
40 d_state = STATE_SYNC_SEARCH;
45 gr_ofdm_frame_sink::enter_have_sync()
48 fprintf(stderr, "@ enter_have_sync\n");
50 d_state = STATE_HAVE_SYNC;
52 // clear state of demapper
57 d_headerbytelen_cnt = 0;
61 gr_ofdm_frame_sink::enter_have_header()
63 d_state = STATE_HAVE_HEADER;
65 // header consists of two 16-bit shorts in network byte order
66 // payload length is lower 12 bits
67 // whitener offset is upper 4 bits
68 d_packetlen = (d_header >> 16) & 0x0fff;
69 d_packet_whitener_offset = (d_header >> 28) & 0x000f;
73 fprintf(stderr, "@ enter_have_header (payload_len = %d) (offset = %d)\n",
74 d_packetlen, d_packet_whitener_offset);
78 unsigned char gr_ofdm_frame_sink::slicer(const gr_complex x)
80 unsigned int table_size = d_sym_value_out.size();
81 unsigned int min_index = 0;
82 float min_euclid_dist = norm(x - d_sym_position[0]);
83 float euclid_dist = 0;
85 for (unsigned int j = 1; j < table_size; j++){
86 euclid_dist = norm(x - d_sym_position[j]);
87 if (euclid_dist < min_euclid_dist){
88 min_euclid_dist = euclid_dist;
92 return d_sym_value_out[min_index];
95 unsigned int gr_ofdm_frame_sink::demapper(const gr_complex *in,
98 unsigned int i=0, bytes_produced=0;
100 while(i < d_occupied_carriers) {
102 d_partial_byte |= d_resid;
103 d_byte_offset += d_nresid;
108 while((d_byte_offset < 8) && (i < d_occupied_carriers)) {
109 //fprintf(stderr, "%f+j%f = %d\n", in[i].real(), in[i].imag(), slicer(in[i]));
110 unsigned char bits = slicer(in[i++]);
111 if((8 - d_byte_offset) >= d_nbits) {
112 d_partial_byte |= bits << (d_byte_offset);
113 d_byte_offset += d_nbits;
116 d_nresid = d_nbits-(8-d_byte_offset);
117 int mask = ((1<<(8-d_byte_offset))-1);
118 d_partial_byte |= (bits & mask) << d_byte_offset;
119 d_resid = bits >> (8-d_byte_offset);
120 d_byte_offset += (d_nbits - d_nresid);
122 //printf("demod symbol: %.4f + j%.4f bits: %x partial_byte: %x byte_offset: %d resid: %x nresid: %d\n",
123 // in[i-1].real(), in[i-1].imag(), bits, d_partial_byte, d_byte_offset, d_resid, d_nresid);
126 if(d_byte_offset == 8) {
127 //printf("demod byte: %x \n\n", d_partial_byte);
128 out[bytes_produced++] = d_partial_byte;
134 return bytes_produced;
138 gr_ofdm_frame_sink_sptr
139 gr_make_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,
140 const std::vector<unsigned char> &sym_value_out,
141 gr_msg_queue_sptr target_queue, unsigned int occupied_carriers)
143 return gr_ofdm_frame_sink_sptr(new gr_ofdm_frame_sink(sym_position, sym_value_out,
144 target_queue, occupied_carriers));
148 gr_ofdm_frame_sink::gr_ofdm_frame_sink(const std::vector<gr_complex> &sym_position,
149 const std::vector<unsigned char> &sym_value_out,
150 gr_msg_queue_sptr target_queue, unsigned int occupied_carriers)
151 : gr_sync_block ("ofdm_frame_sink",
152 gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char)),
153 gr_make_io_signature (0, 0, 0)),
154 d_target_queue(target_queue), d_occupied_carriers(occupied_carriers),
155 d_byte_offset(0), d_partial_byte(0),
156 d_resid(0), d_nresid(0)
158 d_bytes_out = new unsigned char[d_occupied_carriers];
160 set_sym_value_out(sym_position, sym_value_out);
165 gr_ofdm_frame_sink::~gr_ofdm_frame_sink ()
167 delete [] d_bytes_out;
171 gr_ofdm_frame_sink::set_sym_value_out(const std::vector<gr_complex> &sym_position,
172 const std::vector<unsigned char> &sym_value_out)
174 if (sym_position.size() != sym_value_out.size())
177 if (sym_position.size()<1)
180 d_sym_position = sym_position;
181 d_sym_value_out = sym_value_out;
182 d_nbits = (unsigned long)(log10(d_sym_value_out.size()) / log10(2));
189 gr_ofdm_frame_sink::work (int noutput_items,
190 gr_vector_const_void_star &input_items,
191 gr_vector_void_star &output_items)
193 const gr_complex *in = (const gr_complex *) input_items[0];
194 const char *sig = (const char *) input_items[1];
196 unsigned int bytes=0;
199 fprintf(stderr,">>> Entering state machine\n");
201 bytes = demapper(&in[0], d_bytes_out);
205 case STATE_SYNC_SEARCH: // Look for flag indicating beginning of pkt
207 fprintf(stderr,"SYNC Search, noutput=%d\n", noutput_items);
209 if (sig[0]) { // Found it, set up for header decode
214 case STATE_HAVE_SYNC:
217 printf("ERROR -- Found SYNC in HAVE_SYNC\n");
218 fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n",
219 d_headerbytelen_cnt, d_header);
224 d_header = (d_header << 8) | (d_bytes_out[j] & 0xFF);
227 if (++d_headerbytelen_cnt == HEADERBYTELEN) {
230 fprintf(stderr, "got header: 0x%08x\n", d_header);
232 // we have a full header, check to see if it has been received properly
237 printf("\nPacket Length: %d\n", d_packetlen);
239 while((j < bytes) && (d_packetlen_cnt < d_packetlen)) {
240 d_packet[d_packetlen_cnt++] = d_bytes_out[j++];
243 if(d_packetlen_cnt == d_packetlen) {
244 gr_message_sptr msg =
245 gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen);
246 memcpy(msg->msg(), d_packet, d_packetlen_cnt);
247 d_target_queue->insert_tail(msg); // send it
248 msg.reset(); // free it up
254 enter_search(); // bad header
260 case STATE_HAVE_HEADER:
263 printf("ERROR -- Found SYNC in HAVE_HEADER at %d, length of %d\n", d_packetlen_cnt, d_packetlen);
264 fprintf(stderr,"Packet Build\n");
269 d_packet[d_packetlen_cnt++] = d_bytes_out[j++];
271 if (d_packetlen_cnt == d_packetlen){ // packet is filled
273 // NOTE: passing header field as arg1 is not scalable
274 gr_message_sptr msg =
275 gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen_cnt);
276 memcpy(msg->msg(), d_packet, d_packetlen_cnt);
278 d_target_queue->insert_tail(msg); // send it
279 msg.reset(); // free it up