fun_ofdm  1.0
802.11a Physical Layer for USRP
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Macros Pages
fun::ppdu Class Reference

The ppdu class. More...

#include <ppdu.h>

Public Member Functions

 ppdu ()
 Default constructor for empty ppdu. More...
 
 ppdu (Rate rate, int length)
 Constructor for ppdu with rate and length known. More...
 
 ppdu (std::vector< unsigned char > payload, Rate rate)
 Constructor for ppdu with payload and Rate known. More...
 
std::vector< std::complex
< double > > 
encode ()
 Public interface for encoding a ppdu. More...
 
bool decode_header (std::vector< std::complex< double > > samples)
 Public interface for decoding a plcp_header. More...
 
bool decode_data (std::vector< std::complex< double > > samples)
 Public interface for decoding the PHY payload into a PPDU. More...
 
Rate get_rate ()
 Get this PPDU's PHY tx rate. More...
 
int get_length ()
 Get this PPDU's payload length. More...
 
int get_num_symbols ()
 Get the number of OFDM symbols in this PPDU. More...
 
std::vector< unsigned char > get_payload ()
 Get the payload of this PPDU. More...
 

Private Member Functions

std::vector< std::complex
< double > > 
encoder_header ()
 Encodes this PPDU's header. The header is always encoded with BPSK modulation and 1/2 rate convolutional code. More...
 
std::vector< std::complex
< double > > 
encode_data ()
 Encodes this PPDU's payload. The payload is encoded at the rate specified in the header.rate field. More...
 

Private Attributes

plcp_header header
 This PPDU's header parameters. More...
 
std::vector< unsigned char > payload
 This PPDU's payload. More...
 

Detailed Description

The ppdu class.

The ppdu class is a container for a ppdu which is made up of a PHY Header, otherwise known as a PLCP Header, and a payload of bytes. The class also has functions for encoding and decoding the header and payload based on the PHY transmission rates.

Definition at line 85 of file ppdu.h.

Constructor & Destructor Documentation

fun::ppdu::ppdu ( )

Default constructor for empty ppdu.

This constructor creates an empty PPDU with the default/empty plcp_header constructor

Definition at line 26 of file ppdu.cpp.

References header, MAX_FRAME_SIZE, and payload.

27  {
28  header = plcp_header();
29  payload.reserve(MAX_FRAME_SIZE);
30  }
fun::ppdu::ppdu ( Rate  rate,
int  length 
)

Constructor for ppdu with rate and length known.

Parameters
ratePHY Rate for this frame.
lengthLength of payload in bytes.

This constructor creates a PPDU with a header, but no payload field.

Definition at line 35 of file ppdu.cpp.

References fun::RateParams::dbps, header, MAX_FRAME_SIZE, and payload.

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  }
fun::ppdu::ppdu ( std::vector< unsigned char >  payload,
Rate  rate 
)

Constructor for ppdu with payload and Rate known.

Parameters
payloadThe payload/data/MPDU to be transmitted.
rateThe PHY rate for this frame.

This constructor creates a complete PPDU with header and payload.

Definition at line 49 of file ppdu.cpp.

References fun::RateParams::dbps, and header.

49  :
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  }

Member Function Documentation

bool fun::ppdu::decode_data ( std::vector< std::complex< double > >  samples)

Public interface for decoding the PHY payload into a PPDU.

Parameters
samplesComplex samples representing the encoded payload symbols.
Returns
boolean of whether decoding the payload was successful or not based on calculating and comparing the IEEE CRC-32 appended to the end of the payload. If successful the object's payload field is populated with the decoded payload/MPDU.

Definition at line 223 of file ppdu.cpp.

References fun::viterbi::conv_decode(), fun::RateParams::dbps, fun::interleaver::deinterleave(), fun::modulator::demodulate(), fun::puncturer::depuncture(), header, fun::plcp_header::length, payload, fun::plcp_header::rate, and fun::plcp_header::service.

Referenced by fun::frame_decoder::work().

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  }
bool fun::ppdu::decode_header ( std::vector< std::complex< double > >  samples)

Public interface for decoding a plcp_header.

Parameters
samplesComplex samples representing the encoded header symbol.
Returns
boolean of whether decoding the header was successful or not based on checking/comparing the 1 bit parity field in the header. If successful the object's header field is populated appropriately with the decoded fields.

Definition at line 168 of file ppdu.cpp.

References fun::viterbi::conv_decode(), fun::RateParams::dbps, fun::interleaver::deinterleave(), fun::modulator::demodulate(), fun::RateParams::FromRateField(), header, fun::plcp_header::length, fun::plcp_header::num_symbols, fun::parity(), fun::plcp_header::rate, fun::RateParams::rate, fun::RATE_1_2_BPSK, and fun::VALID_RATES.

Referenced by fun::frame_decoder::work().

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  }
std::vector< std::complex< double > > fun::ppdu::encode ( )

Public interface for encoding a ppdu.

Returns
Modulated data as a vector of complex doubles

Public wrapper for encoding the header & payload and concatenating them together into a PHY frame.

Definition at line 65 of file ppdu.cpp.

References encode_data(), and encoder_header().

Referenced by fun::frame_builder::build_frame().

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  }
std::vector< std::complex< double > > fun::ppdu::encode_data ( )
private

Encodes this PPDU's payload. The payload is encoded at the rate specified in the header.rate field.

Returns
The modulated data.

Definition at line 112 of file ppdu.cpp.

References fun::viterbi::conv_encode(), fun::RateParams::dbps, header, fun::interleaver::interleave(), fun::modulator::modulate(), payload, fun::puncturer::puncture(), and fun::plcp_header::rate.

Referenced by encode().

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  }
std::vector< std::complex< double > > fun::ppdu::encoder_header ( )
private

Encodes this PPDU's header. The header is always encoded with BPSK modulation and 1/2 rate convolutional code.

Returns
The modulated header symbol.

Uses the rate_params to build the header. Note the header is NOT scrambled. Codes the header using a 1/2 convolutional code. Interleaves the header. And finally modulates the header using BPSK modulation.

Definition at line 81 of file ppdu.cpp.

References fun::viterbi::conv_encode(), header, fun::interleaver::interleave(), fun::plcp_header::length, fun::modulator::modulate(), fun::parity(), fun::plcp_header::rate, fun::RATE_1_2_BPSK, and fun::RateParams::rate_field.

Referenced by encode().

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  }
int fun::ppdu::get_length ( )
inline

Get this PPDU's payload length.

Definition at line 144 of file ppdu.h.

References header, and fun::plcp_header::length.

Referenced by fun::frame_decoder::work().

int fun::ppdu::get_num_symbols ( )
inline

Get the number of OFDM symbols in this PPDU.

Definition at line 145 of file ppdu.h.

References header, and fun::plcp_header::num_symbols.

Referenced by fun::frame_decoder::work().

std::vector<unsigned char> fun::ppdu::get_payload ( )
inline

Get the payload of this PPDU.

Definition at line 146 of file ppdu.h.

References payload.

Referenced by fun::frame_decoder::work().

Rate fun::ppdu::get_rate ( )
inline

Get this PPDU's PHY tx rate.

Definition at line 143 of file ppdu.h.

References header, and fun::plcp_header::rate.

Referenced by fun::frame_decoder::work().

Member Data Documentation

plcp_header fun::ppdu::header
private

This PPDU's header parameters.

Definition at line 150 of file ppdu.h.

Referenced by decode_data(), decode_header(), encode_data(), encoder_header(), get_length(), get_num_symbols(), get_rate(), and ppdu().

std::vector<unsigned char> fun::ppdu::payload
private

This PPDU's payload.

Definition at line 151 of file ppdu.h.

Referenced by decode_data(), encode_data(), get_payload(), and ppdu().


The documentation for this class was generated from the following files: