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);
77 unsigned char gr_ofdm_frame_sink::bpsk_slicer(gr_complex x)
79 return (unsigned char)(x.real() > 0 ? 1 : 0);
82 unsigned char gr_ofdm_frame_sink::qpsk_slicer(gr_complex x)
84 unsigned char i = (x.real() > 0 ? 1 : 0);
85 unsigned char q = (x.imag() > 0 ? 1 : 0);
90 unsigned int gr_ofdm_frame_sink::bpsk_demapper(const gr_complex *in,
93 unsigned int i=0, bytes_produced=0;
95 while(i < d_occupied_carriers) {
97 while((d_byte_offset < 8) && (i < d_occupied_carriers)) {
98 //fprintf(stderr, "%f+j%f\n", in[i].real(), in[i].imag());
99 d_partial_byte |= bpsk_slicer(in[i++]) << (d_byte_offset++);
102 if(d_byte_offset == 8) {
103 out[bytes_produced++] = d_partial_byte;
109 return bytes_produced;
112 unsigned int gr_ofdm_frame_sink::qpsk_demapper(const gr_complex *in,
115 unsigned int i=0, bytes_produced=0;
117 while(i < d_occupied_carriers) {
119 while((d_byte_offset < 8) && (i < d_occupied_carriers)) {
120 //fprintf(stderr, "%f+j%f\n", in[i].real(), in[i].imag());
121 d_partial_byte |= qpsk_slicer(in[i++]) << (d_byte_offset);
125 if(d_byte_offset == 8) {
126 out[bytes_produced++] = d_partial_byte;
132 return bytes_produced;
135 gr_ofdm_frame_sink_sptr
136 gr_make_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_carriers,
137 const std::string &mod)
139 return gr_ofdm_frame_sink_sptr(new gr_ofdm_frame_sink(target_queue, occupied_carriers, mod));
143 gr_ofdm_frame_sink::gr_ofdm_frame_sink(gr_msg_queue_sptr target_queue, unsigned int occupied_carriers,
144 const std::string &mod)
145 : gr_sync_block ("ofdm_frame_sink",
146 gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char)),
147 gr_make_io_signature (0, 0, 0)),
148 d_target_queue(target_queue), d_occupied_carriers(occupied_carriers),
149 d_byte_offset(0), d_partial_byte(0)
151 d_bytes_out = new unsigned char[(int)ceil(d_occupied_carriers/4.0)];
154 d_demapper = &gr_ofdm_frame_sink::qpsk_demapper;
156 else if(mod == "bpsk") {
157 d_demapper = &gr_ofdm_frame_sink::bpsk_demapper;
160 throw std::invalid_argument("Modulation type must be BPSK or QPSK.");
166 gr_ofdm_frame_sink::~gr_ofdm_frame_sink ()
168 delete [] d_bytes_out;
172 gr_ofdm_frame_sink::work (int noutput_items,
173 gr_vector_const_void_star &input_items,
174 gr_vector_void_star &output_items)
176 const gr_complex *in = (const gr_complex *) input_items[0];
177 const char *sig = (const char *) input_items[1];
179 unsigned int bytes=0;
182 fprintf(stderr,">>> Entering state machine\n");
184 //bytes = bpsk_demapper(&in[0], d_bytes_out);
185 bytes = (this->*d_demapper)(&in[0], d_bytes_out);
189 case STATE_SYNC_SEARCH: // Look for flag indicating beginning of pkt
191 fprintf(stderr,"SYNC Search, noutput=%d\n", noutput_items);
193 if (sig[0]) { // Found it, set up for header decode
198 case STATE_HAVE_SYNC:
201 printf("ERROR -- Found SYNC in HAVE_SYNC\n");
202 fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n",
203 d_headerbytelen_cnt, d_header);
208 d_header = (d_header << 8) | (d_bytes_out[j] & 0xFF);
211 if (++d_headerbytelen_cnt == HEADERBYTELEN) {
214 fprintf(stderr, "got header: 0x%08x\n", d_header);
216 // we have a full header, check to see if it has been received properly
221 printf("\nPacket Length: %d\n", d_packetlen);
223 while((j < bytes) && (d_packetlen_cnt < d_packetlen)) {
224 d_packet[d_packetlen_cnt++] = d_bytes_out[j++];
227 if(d_packetlen_cnt == d_packetlen) {
228 gr_message_sptr msg =
229 gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen);
230 memcpy(msg->msg(), d_packet, d_packetlen_cnt);
231 d_target_queue->insert_tail(msg); // send it
232 msg.reset(); // free it up
238 enter_search(); // bad header
244 case STATE_HAVE_HEADER:
247 printf("ERROR -- Found SYNC in HAVE_HEADER at %d, length of %d\n", d_packetlen_cnt, d_packetlen);
248 fprintf(stderr,"Packet Build\n");
253 d_packet[d_packetlen_cnt++] = d_bytes_out[j++];
255 if (d_packetlen_cnt == d_packetlen){ // packet is filled
257 // NOTE: passing header field as arg1 is not scalable
258 gr_message_sptr msg =
259 gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen_cnt);
260 memcpy(msg->msg(), d_packet, d_packetlen_cnt);
262 d_target_queue->insert_tail(msg); // send it
263 msg.reset(); // free it up