fun_ofdm  1.0
802.11a Physical Layer for USRP
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Macros Pages
ppdu.cpp
Go to the documentation of this file.
1 
10 #include <arpa/inet.h>
11 #include <boost/crc.hpp>
12 #include <iostream>
13 
14 #include "ppdu.h"
15 #include "parity.h"
16 #include "viterbi.h"
17 #include "interleaver.h"
18 #include "puncturer.h"
19 #include "modulator.h"
20 
21 namespace fun
22 {
27  {
28  header = plcp_header();
29  payload.reserve(MAX_FRAME_SIZE);
30  }
31 
35  ppdu::ppdu(Rate rate, int length)
36  {
37  RateParams rate_params = RateParams(rate);
38  int num_symbols = std::ceil(
39  double((16 /* service */ + 8 * (length + 4 /* CRC */) + 6 /* tail */)) /
40  double(rate_params.dbps));
41  header = plcp_header(rate, length, num_symbols);
42  payload.reserve(MAX_FRAME_SIZE);
43  }
44 
45 
49  ppdu::ppdu(std::vector<unsigned char> payload, Rate rate) :
50  payload(payload)
51  {
52  RateParams rate_params = RateParams(rate);
53  int length = payload.size();
54  int num_symbols = std::ceil(
55  double((16 /* service */ + 8 * (length + 4 /* CRC */) + 6 /* tail */)) /
56  double(rate_params.dbps));
57 
58  header = plcp_header(rate, length, num_symbols);
59  }
60 
65  std::vector<std::complex<double> > ppdu::encode()
66  {
67  std::vector<std::complex<double> > header_samples = encoder_header();
68  std::vector<std::complex<double> > payload_samples = encode_data();
69  std::vector<std::complex<double> > ppdu_samples = std::vector<std::complex<double> >(header_samples.size() + payload_samples.size());
70  memcpy(&ppdu_samples[0], &header_samples[0], header_samples.size() * sizeof(std::complex<double>));
71  memcpy(&ppdu_samples[48], payload_samples.data(), payload_samples.size() * sizeof(std::complex<double>));
72  return ppdu_samples;
73  }
74 
75 
81  std::vector<std::complex<double> > ppdu::encoder_header()
82  {
83  // Build the header from the rate field and length
84  RateParams rate_params = RateParams(header.rate);
85  unsigned int header_field = 0;
86  header_field = ((rate_params.rate_field & 0xF) << 13) | (header.length & 0xFFF);
87 
88  // Set the parity bit and align
89  if(parity(header_field) == 1) header_field |= 131072;
90  header_field <<= 6;
91 
92  // Convert the header to a unsigned char array
93  unsigned char header_bytes[4];
94  unsigned int h = htonl(header_field) >> 8;
95  memcpy(header_bytes, &h, 3);
96 
97  // Convolutionally encode the header
98  std::vector<unsigned char> header_symbols(48 /* header is always a single 1/2 BPSK symbol */);
99  viterbi v;
100  v.conv_encode(header_bytes, &header_symbols[0], 18 /* header is always 18 data bits */);
101 
102  // Interleave the header
103  std::vector<unsigned char> interleaved = interleaver::interleave(header_symbols);
104 
105  // Modulate the header
106  std::vector<std::complex<double> > modulated = modulator::modulate(interleaved, RATE_1_2_BPSK);
107 
108  return modulated;
109 
110  }
111 
112  std::vector<std::complex<double> > ppdu::encode_data()
113  {
114  // Get the RateParams
115  RateParams rate_params = RateParams(header.rate);
116 
117  // Calculate the number of symbols
118  int num_symbols = std::ceil(
119  double((16 /* service */ + 8 * (payload.size() + 4 /* CRC */) + 6 /* tail */)) /
120  double(rate_params.dbps));
121 
122  // Calculate the number of data bits/bytes (including padding bits)
123  int num_data_bits = num_symbols * rate_params.dbps;
124  int num_data_bytes = num_data_bits / 8;
125 
126  unsigned short service_field = 0;
127 
128  // Concatenate the service and payload
129  std::vector<unsigned char> data(num_data_bytes+1, 0);
130  memcpy(&data[0], &service_field, 2);
131  memcpy(&data[2], payload.data(), payload.size());
132 
133  // Calcualate and append the CRC
134  boost::crc_32_type crc;
135  crc.process_bytes(&data[0], 2 + payload.size());
136  unsigned int calculated_crc = crc.checksum();
137  memcpy(&data[2 + payload.size()], &calculated_crc, 4);
138 
139  // Scramble the data
140  std::vector<unsigned char> scrambled(num_data_bytes+1, 0);
141  int state = 93, feedback = 0;
142  for(int x = 0; x < num_data_bytes; x++)
143  {
144  feedback = (!!(state & 64)) ^ (!!(state & 8));
145  scrambled[x] = feedback ^ data[x];
146  state = ((state << 1) & 0x7E) | feedback;
147  }
148  data.swap(scrambled);
149 
150  // Convolutionally encode the data
151  std::vector<unsigned char> data_encoded(num_data_bits * 2, 0);
152  viterbi v;
153  v.conv_encode(&data[0], data_encoded.data(), num_data_bits-6);
154 
155  // Puncture the data
156  std::vector<unsigned char> data_punctured = puncturer::puncture(data_encoded, header.rate);
157 
158  // Interleave the data
159  std::vector<unsigned char> data_interleaved = interleaver::interleave(data_punctured);
160 
161  // Modulated the data
162  std::vector<std::complex<double> > data_modulated = modulator::modulate(data_interleaved, header.rate);
163 
164  return data_modulated;
165  }
166 
167  // Decode a PLCP header from 48 complex samples
168  bool ppdu::decode_header(std::vector<std::complex<double> > samples)
169  {
170  assert(samples.size() == 48);
171 
172  // Demodulate the header
173  std::vector<unsigned char> demodulated = modulator::demodulate(samples, RATE_1_2_BPSK);
174 
175  // Deinterleave the header
176  std::vector<unsigned char> deinterleaved = interleaver::deinterleave(demodulated);
177 
178  // Convolutionally decode the header
179  std::vector<unsigned char> header_bytes(4);
180  viterbi v;
181  v.conv_decode(deinterleaved.data(), header_bytes.data(), 18 /* header is always 18 data bits */);
182 
183  // Verify header parity
184  unsigned int header_field;
185  memcpy(&header_field, &header_bytes[0], 3);
186  header_field = htonl(header_field) >> 8;
187  int par = parity(header_field);
188  if(par == 1)
189  {
190  return false;
191  }
192 
193  // Get the rate field and length
194  unsigned char rate_field = ((header_field >> 19) & 0xF);
195  unsigned int length = ((header_field >> 6) & 0xFFF);
196 
197  // Check for a valid rate
198  bool valid_rate = false;
199  for(int x = 0; x < VALID_RATES.size(); x++) if(VALID_RATES[x] == rate_field) valid_rate = true;
200  if(!valid_rate)
201  {
202  return false;
203  }
204 
205  // Calculate the number of symbols
206  RateParams rate_params = RateParams::FromRateField(rate_field);
207  int num_symbols = std::ceil(
208  double((16 /* service */ + 8 * (length + 4 /* CRC */) + 6 /* tail */)) /
209  double(rate_params.dbps));
210 
211  // Populate the header fields
212  header.length = length;
214  header.num_symbols = num_symbols;
215 
216  // Indicate success
217  return true;
218  }
219 
220 
221 
222 
223  bool ppdu::decode_data(std::vector<std::complex<double> > samples)
224  {
225  // Get the RateParams
226  RateParams rate_params = RateParams(header.rate);
227 
228  // Calculate the number of symbols
229  int num_symbols = std::ceil(
230  double((16 /* service */ + 8 * (header.length + 4 /* CRC */) + 6 /* tail */)) /
231  double(rate_params.dbps));
232 
233  // Calculate the number of data bits/bytes (including padding bits)
234  int num_data_bits = num_symbols * rate_params.dbps;
235  int num_data_bytes = num_data_bits / 8;
236 
237  // Demodulate the data
238  std::vector<unsigned char> demodulated = modulator::demodulate(samples, header.rate);
239 
240  // Deinterleave the data
241  std::vector<unsigned char> deinterleaved = interleaver::deinterleave(demodulated);
242 
243  // Depuncture the data
244  std::vector<unsigned char> depunctured = puncturer::depuncture(deinterleaved, header.rate);
245 
246  // Convolutionally decode the data
247  int data_bits = 16 /* service */ + (header.length + 4 /* CRC */) * 8 + 6 /* tail bits */;
248  int data_bytes = data_bits / 8 + 1;
249  data_bits = num_data_bits - 6;
250  data_bytes = num_data_bytes;
251  std::vector<unsigned char> decoded(data_bytes);
252  viterbi v;
253  v.conv_decode(&depunctured[0], &decoded[0], data_bits);
254 
255  // Descramble the data
256  std::vector<unsigned char> descrambled(num_data_bytes+1, 0);
257  int state = 93, feedback = 0;
258  for(int x = 0; x < num_data_bytes; x++)
259  {
260  feedback = (!!(state & 64)) ^ (!!(state & 8));
261  descrambled[x] = feedback ^ decoded[x];
262  state = ((state << 1) & 0x7E) | feedback;
263  }
264  decoded.swap(descrambled);
265 
266  // Calculate the CRC
267  boost::crc_32_type crc;
268  crc.process_bytes(&decoded[0], 2 + header.length);
269  unsigned int calculated_crc = crc.checksum();
270  unsigned int given_crc = 0;
271  memcpy(&given_crc, &decoded[2 + header.length], 4);
272 
273  // Verify the CRC
274  if(given_crc != calculated_crc)
275  {
276  std::cerr << "Invalid CRC (length " << header.length << ")" << std::endl;
277  // Indicate failure
278  return false;
279  }
280  else
281  {
282  // Copy the payload
283  // std::vector<unsigned char> payload(length);
284  payload.resize(header.length);
285  memcpy(&payload[0], &decoded[2 /* skip the service field */], header.length);
286 
287  // Fill the output values
288  // data_out.rate = rate;
289  memcpy(&header.service, &decoded[0], 2);
290  // data_out.length = length;
291  // Indicate success
292  return true;
293  }
294 
295  }
296 
297 }
298