115 Commits

Author SHA1 Message Date
Bastian Bloessl fe8d6757ab readme update 2021-07-05 19:42:08 +02:00
mychele da034e9669 Fix d_prev_pilots for symbols 0 and 1 in frame_equalizer_impl.cc 2020-07-30 09:17:28 +02:00
Bastian Bloessl 80dd9038c7 update readme
# Conflicts:
#	README.md
2019-06-06 12:12:46 +02:00
Bastian Bloessl 08787e1ddb mac: make max frame size configurable 2018-04-10 17:47:31 +01:00
Bastian Bloessl be0e79d41b Merge pull request #105 from jkbecker/foundatypo
typo fix
2018-03-31 13:10:40 +02:00
Johannes Becker e8922f3e3a another typo 2018-03-27 15:56:10 -04:00
Johannes Becker 0d5c8c60c7 typo fix 2018-03-27 15:43:29 -04:00
Bastian Bloessl 2d3201c7a1 readme: update link 2017-11-15 13:58:56 +00:00
Ravi Sharan 54ef06a167 Fix doxygen documentation build
Swig (which uses doxygen) is included before the docs,
so the doxygen is not initialized
2017-10-24 13:28:21 +02:00
Bastian Bloessl 26a0c2c87e equalizer: make interleaver pattern a constant 2017-08-09 22:38:39 +01:00
Bastian Bloessl d90b28c55b mapper: make scrambler init a class variable 2017-08-09 22:38:34 +01:00
Bastian Bloessl 6dc42c7f43 sync: more logging 2017-08-09 22:38:31 +01:00
Bastian Bloessl 44561c1578 decode: make pmt output optional 2017-04-09 16:42:00 +02:00
Bastian Bloessl 951d8fd547 cmake: require swig 2017-03-17 15:12:31 +01:00
Bastian Bloessl 21bcc8b639 equalizer: exclude guards from SNR calculation
Thanks to Stephen Wolfe for reporting
2017-03-06 12:48:05 +01:00
Bastian Bloessl 691cf04a8f readme: add swig dependency 2017-02-22 17:11:59 +01:00
Bastian Bloessl 0f5215d921 add note to rx demo script 2016-10-11 14:38:37 +02:00
Bastian Bloessl 4a1bd44033 rx flow graph: delete unused encoding parameter 2016-09-29 13:14:27 +02:00
Bastian Bloessl f7365d081a phy hier: make mac in optional 2016-09-21 12:02:51 +02:00
Bastian Bloessl 3523807c09 phy hier: make mac out port optional 2016-09-21 10:12:36 +02:00
Bastian Bloessl 84c9ff3e0d utils: fix macro 2016-09-20 14:32:59 +02:00
Bastian Bloessl 285a0e2558 switch to QT GUI 2016-09-15 11:37:27 +02:00
Bastian Bloessl 0bd2e30f55 fix frequency offset calculation 2016-09-05 15:41:27 +02:00
Bastian Bloessl 8530b92086 whitespace 2016-09-05 09:15:49 +02:00
Andrei Stoica 26514acfef Fixed logging of STA algo selection for equalization 2016-09-05 09:11:42 +02:00
Bastian Bloessl 95b4798c6b Merge pull request #45 from rstoica/master
Fixed typo in default switch case for SIGNAL field parsing
2016-08-31 11:57:48 +02:00
Andrei Stoica 743504ccdd Fixed typo in default switch case for SIGNAL field parsing 2016-08-31 11:46:56 +02:00
Bastian Bloessl fff13b2443 flow graphs: use normalized gain 2016-08-31 08:47:52 +02:00
Bastian Bloessl 88e17d6176 convert metadata to dict 2016-08-31 08:43:00 +02:00
Jonathan Brucker bef6e3d962 Add nomfreq, freqofs, dlt to PDU metadata
Add Nominal Frequency, Carrier Frequency Offset and Data Link Type (DLT)
tags to PDU.

Signed-off-by: Jonathan Brucker jonathan.brucke@gmail.com
2016-08-30 16:15:54 +00:00
Bastian Bloessl da1b0eb713 adapt simulations to GNU Radio GRC changes 2016-08-27 14:16:01 +02:00
Bastian Bloessl 23a195311a fix buffer size allocation 2016-08-22 15:35:10 +02:00
Bastian Bloessl 43abd875d9 Merge pull request #42 from kantooon/next
Add SSE2 build flag for Debian
2016-08-21 10:01:27 +02:00
Adrian Musceac c1fde325a5 Add SSE2 build flag for Debian 2016-08-20 19:57:48 +01:00
Bastian Bloessl baa5b07152 link parameters also in transceiver 2016-08-08 20:50:31 +02:00
Bastian Bloessl f543a8598c Merge pull request #40 from jonathanbrucker/master
bugfix: link between EQ parameters and simulation parameters
2016-08-08 20:46:35 +02:00
Jonathan Brucker ba50c10a02 bugfix: link between EQ parameters and simulation parameters
The EQ parameters (bw, freq) should be updated from simulation
parameters, instead of using constants (10e6, 5.8G).

Signed-off-by: Jonathan Brucker <jonathan.brucke@gmail.com>
2016-08-08 15:35:33 +00:00
Bastian Bloessl 68158e14f7 update readme 2016-08-07 15:14:48 +02:00
Bastian Bloessl 58b3ffb94d simulations: import os 2016-06-22 19:03:52 +02:00
Bastian Bloessl d16559b105 update flow graphs 2016-06-22 13:00:27 +02:00
Bastian Bloessl c3195613ba update grc files 2016-06-22 13:00:20 +02:00
Bastian Bloessl cc0a56e341 Merge branch 'master' into development
# Conflicts:
#	examples/wifi_loopback.grc
#	examples/wifi_transceiver.grc
#	examples/wifi_tx.grc
#	grc/ieee802_11_decode_mac.xml
#	grc/ieee802_11_mac.xml
#	grc/ieee802_11_mapper.xml
#	grc/ieee802_11_ofdm_decode_signal.xml
#	grc/ieee802_11_ofdm_equalize_symbols.xml
#	grc/ieee802_11_parse_mac.xml
#	grc/ieee802_11_sync_long.xml
#	grc/ieee802_11_sync_short.xml
2016-06-22 12:58:11 +02:00
Bastian Bloessl 5ddba507e5 update flow graphs 2016-06-22 12:52:48 +02:00
Bastian Bloessl 397e9faaaa update grc files 2016-06-22 12:52:40 +02:00
Bastian Bloessl 30862c0ff8 update simulation results 2016-05-31 18:14:50 +02:00
Bastian Bloessl 0b833da040 add sensitivity simulations 2016-05-31 15:40:52 +02:00
Bastian Bloessl c05497dc19 move awg simulations to root 2016-05-31 15:40:43 +02:00
Bastian Bloessl ece3cbf5bb git rid of itpp 2016-05-31 15:40:29 +02:00
Bastian Bloessl c3291917c8 update flow graphs 2016-05-31 15:40:18 +02:00
Bastian Bloessl d1d33c90eb use viterbi decoder in mac 2016-05-31 15:40:07 +02:00
Bastian Bloessl 1ed08f6e9a restructure receiver 2016-05-31 15:39:15 +02:00
Bastian Bloessl dd89949184 chunks to symbols: use constellations 2016-05-31 15:37:28 +02:00
Bastian Bloessl 9ca1f310f5 sync long: signal freq offset 2016-05-31 15:36:40 +02:00
Bastian Bloessl aa8d43508e sync short: signal freq offset 2016-05-31 15:36:25 +02:00
Bastian Bloessl 052d5022b0 add equalizers 2016-05-31 15:36:05 +02:00
Bastian Bloessl 5a9846fa67 put viterbi decoder in separate file 2016-05-31 15:35:22 +02:00
Bastian Bloessl 6bcf462aa5 channel scrip fix permissions 2016-05-31 15:32:56 +02:00
Bastian Bloessl 325c0400d2 add editorconfig 2016-05-31 15:32:39 +02:00
Bastian Bloessl 4c710aec25 update gitignore 2016-05-31 15:32:27 +02:00
Bastian Bloessl 7f95f47ec6 add wifi constellation objects 2016-05-31 15:32:18 +02:00
Bastian Bloessl f9aa4b5ec2 remove wifi prefix, update flow graphs
# Conflicts:
#	examples/wifi_loopback.grc
#	examples/wifi_phy_hier.grc
#	examples/wifi_rx.grc
#	examples/wifi_transceiver.grc
#	examples/wifi_tx.grc
2016-04-20 07:46:49 +02:00
Bastian Bloessl 760fc86101 rename 2016-04-20 07:45:49 +02:00
Gonzalo Arcos 0f56254df3 - Added new Viterbi convolutional decoder to the OFDM Decode Mac block replacing the former IT++ version. This new decoder uses
SSE2 and improves the performance significantly. The decoder was taken from the gr-dvbt module from GNU Radio.
- Disabled some logging functions in the ofdm_mac and ofdm_decode_signal blocks that were degrading the performance significantly.

[Gonzalo Arcos | Rodrigo Ferreri]
2016-04-20 06:53:49 +02:00
Gonzalo Arcos 74ae445143 Replaced demodulation algorithms in OFDM Decode MAC block for a more efficient version.
[Gonzalo Arcos | Rodrigo Ferreri]
2016-04-20 06:43:13 +02:00
Bastian Bloessl 3703abbbf1 flow graph: fix channels 2016-04-12 09:35:28 +02:00
Bastian Bloessl fb14006c4b add script to output wifi channels 2016-04-12 09:35:11 +02:00
Bastian Bloessl b16ac24359 Throw Error if Swig or Python is not found. 2016-03-08 15:50:25 -08:00
Bastian Bloessl e815faa792 fix use after free 2016-03-01 15:35:42 -08:00
Bastian Bloessl 298d9823cc update cmake files 2016-01-08 02:02:02 -08:00
Bastian Bloessl 17abd32ca9 flow graphs: move blocks around 2015-12-08 14:14:33 -08:00
Bastian Bloessl 9d593483bf flow graphs: lo_offset by default 2015-12-08 12:53:59 -08:00
Bastian Bloessl 4a43c572b3 wifi_tx: remove antenna parameter 2015-12-08 12:52:58 -08:00
Bastian Bloessl 253c26c48f sim: simplify Makefile 2015-11-30 21:03:48 -08:00
Bastian Bloessl ae168184bc simulation: add plot 2015-11-30 13:26:12 -08:00
Bastian Bloessl 566de26230 simulation: remove useless sleep 2015-11-30 13:26:12 -08:00
Bastian Bloessl 01d40ec00b simulation: make plot script non-interactive 2015-11-30 13:26:12 -08:00
Bastian Bloessl 0e11d51b01 simulations: make parser a shell script 2015-11-30 13:26:11 -08:00
Bastian Bloessl 77ed9e84c2 simulations: refactor parse script to plot script 2015-11-30 13:26:11 -08:00
Bastian Bloessl 3ae290ec87 simulations: adapt makefile 2015-11-30 13:26:11 -08:00
Bastian Bloessl 72d089d9cc gitignore: do not track simulation results 2015-11-30 13:26:11 -08:00
Bastian Bloessl a47ae95ce5 simulation: fix flow graph 2015-11-30 13:26:11 -08:00
Bastian Bloessl b781cea7eb sim: change directory structure 2015-11-30 07:06:24 -08:00
theano 81ff17ccd5 move legend in plot 2015-11-30 07:01:05 -08:00
theano 246c394658 Adjusted multiplier block to correct value 2015-11-30 07:01:05 -08:00
theano 676963604f power evaluation 2015-11-30 07:01:05 -08:00
theano 3ba472ab7c rework Makefile, parse file 2015-11-30 07:01:05 -08:00
theano 2853ddaa00 change stdev to confidence intervals in plot, clean up parse script 2015-11-30 07:01:05 -08:00
theano a42e59c5b9 fix blank plot save issue 2015-11-30 07:01:05 -08:00
theano fd64759c5a remove results files 2015-11-30 07:01:05 -08:00
theano 39017c8b20 change some parameters 2015-11-30 07:01:04 -08:00
theano a812150eac add ability to run multiple trials, add error bars 2015-11-30 07:01:04 -08:00
theano 016616d915 still trying to remove results files 2015-11-30 07:01:04 -08:00
theano 9176a3d615 remove result files and move gitignore to its right place... 2015-11-30 07:01:04 -08:00
theano 7e793f0d5b ignore results 2015-11-30 07:01:04 -08:00
theano 9b7c568868 Fix derp with results filename, autosave plot 2015-11-30 07:01:04 -08:00
theano c0fab12da3 add LUT for encodings; make varnames more explicit; update plot labels and title 2015-11-30 07:01:04 -08:00
theano 66ab958b6e enable outdir name specification 2015-11-30 07:01:04 -08:00
Diyu 940a1a1ccf update version 2015-11-30 07:01:03 -08:00
Diyu 39db4c91e8 add parse.py in run 2015-11-30 07:01:03 -08:00
Diyu 06c2e09234 Add initial Makefile and figure print. Change the wifi_loopback to direct output to result/ 2015-11-30 07:01:03 -08:00
theano 6148463e61 fixed problem where last packet doesn't show up in pcap 2015-11-30 07:01:03 -08:00
theano 63dc634cc4 send fixed number of messages (strings), capture packets 2015-11-30 07:01:03 -08:00
theano 7eae9a9bf9 Create workspace area; make no-gui version of wifi_loopback 2015-11-30 07:01:03 -08:00
Bastian Bloessl 12f2b0e913 flow graphs: set sensitivity to 0.56 2015-11-30 06:59:22 -08:00
Bastian Bloessl d1d6ed6010 PHY: add sensitivity parameter 2015-11-30 06:55:12 -08:00
Bastian Bloessl 481d873f2e formatting 2015-09-04 14:53:44 +02:00
Bastian Bloessl 009490b8c9 scramble data 2015-09-04 14:53:39 +02:00
Bastian Bloessl 33a75673b2 long: other way to define matched filter 2015-09-04 12:27:44 +02:00
Bastian Bloessl 6fb8a97cfd fix typo 2015-09-01 10:32:52 +02:00
Bastian Bloessl 1eb5ac46ef fix logging 2015-09-01 08:15:11 +02:00
Bastian Bloessl 77548c73a9 rely on config.h to determine logging configuration 2015-08-13 15:11:18 +02:00
Bastian Bloessl 9ba6e4af39 Merge pull request #17 from marcusmueller/cmake_fix_findITPP_for_RelWitDebInfo
cmake: fixed FindITPP for custom prefix, DebWithRelInfo
2015-07-24 16:22:53 +02:00
Marcus Müller 2841634b1c cmake: fixed FindITPP for custom prefix, DebWithRelInfo
* include dir: would only try ${PC_ITPP_INCLUDEDIR}/include:
  * added ${PC_ITPP_INCLUDEDIR} as HINT
* dirs: differentiate between HINTS and PATHS
* ITPP_LIBRARY: Now works with CMAKE_BUILD_TYPE=RelWithDebInfo and
  debug version of libitpp
  * if build type is RelWithDebInfo and both libraries (libitpp and
    libitpp-debug) are present, use debug variant.
2015-07-24 12:04:55 +02:00
Bastian Bloessl b3442dad46 loopback flow graph: set minimum interval for message generation 2015-04-24 10:27:12 +02:00
Bastian Bloessl 123628146e decode signal: fix tag offset 2015-04-24 10:25:36 +02:00
102 changed files with 16022 additions and 16278 deletions
+13
View File
@@ -0,0 +1,13 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
[Makefile]
indent_style = tab
[**.{cc,h,xml}]
indent_style = tab
indent_size = 4
+2
View File
@@ -5,3 +5,5 @@ examples/*.py
.pydevproject .pydevproject
.settings .settings
*.pyc *.pyc
**/.DS_Store
.clang_complete
+17 -17
View File
@@ -37,6 +37,7 @@ if(NOT WIN32)
#http://gcc.gnu.org/wiki/Visibility #http://gcc.gnu.org/wiki/Visibility
add_definitions(-fvisibility=hidden) add_definitions(-fvisibility=hidden)
add_definitions(-std=c++0x) add_definitions(-std=c++0x)
add_definitions(-msse2)
endif() endif()
######################################################################## ########################################################################
@@ -81,29 +82,31 @@ set(GRC_BLOCKS_DIR ${GR_PKG_DATA_DIR}/grc/blocks)
# Find gnuradio build dependencies # Find gnuradio build dependencies
######################################################################## ########################################################################
set(GR_REQUIRED_COMPONENTS RUNTIME FILTER FFT PMT DIGITAL) set(GR_REQUIRED_COMPONENTS RUNTIME FILTER FFT PMT DIGITAL)
find_package(Gnuradio) find_package(Gnuradio)
find_package(CppUnit)
find_package(ITPP)
if(NOT GNURADIO_RUNTIME_FOUND) if(NOT GNURADIO_RUNTIME_FOUND)
message(FATAL_ERROR "GnuRadio Runtime required to compile ieee802-11") message(FATAL_ERROR "GNU Radio required to compile gr-ieee802-11")
endif() endif()
find_package(CppUnit)
if(NOT CPPUNIT_FOUND) if(NOT CPPUNIT_FOUND)
message(FATAL_ERROR "CppUnit required to compile ieee802-11") message(FATAL_ERROR "CppUnit required to compile gr-ieee802-11")
endif() endif()
if(NOT ITPP_FOUND) find_package(Log4cpp)
message(FATAL_ERROR "ITPP required to compile ieee802-11") if (LOG4CPP_FOUND)
message(STATUS "Found LOG4CPP: ${LOG4CPP_LIBRARIES}")
add_definitions("-DGR_IEEE80211_LOG4CPP")
else ()
message(STATUS "LOG4CPP not found (not required).")
endif ()
find_package(SWIG)
if(NOT SWIG_FOUND)
message(FATAL_ERROR "SWIG required to compile gr-ieee802-11")
endif() endif()
######################################################################## find_package(Doxygen)
# Setup logging options
########################################################################
include(GrMiscUtils)
GR_LOGGING()
######################################################################## ########################################################################
# On Apple only, set install name and use rpath correctly, if not already set # On Apple only, set install name and use rpath correctly, if not already set
######################################################################## ########################################################################
@@ -133,16 +136,13 @@ include_directories(
${CMAKE_BINARY_DIR}/include ${CMAKE_BINARY_DIR}/include
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
${CPPUNIT_INCLUDE_DIRS} ${CPPUNIT_INCLUDE_DIRS}
${ITPP_INCLUDE_DIR}
${GNURADIO_RUNTIME_INCLUDE_DIRS} ${GNURADIO_RUNTIME_INCLUDE_DIRS}
${LOG4CPP_INCLUDE_DIRS}
) )
link_directories( link_directories(
${Boost_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS}
${CPPUNIT_LIBRARY_DIRS} ${CPPUNIT_LIBRARY_DIRS}
${GNURADIO_RUNTIME_LIBRARY_DIRS} ${GNURADIO_RUNTIME_LIBRARY_DIRS}
${LOG4CPP_LIBRARY_DIRS}
) )
######################################################################## ########################################################################
+94 -75
View File
@@ -1,45 +1,41 @@
Hi, Hi!
This an IEEE 802.11 a/g/p transceiver for GNU Radio that is fitted for operation
with Ettus N210s and B210s. Interoperability was tested with many off-the-shelf
WiFi cards and IEEE 802.11p prototypes. The code can also be used in
simulations.
# Development
Like GNU Radio, this module uses *master* and *maint* branches for development.
These branches are supposed to be used with the corresponding GNU Radio
branches. This means: the *maint-3.7* branch is compatible with GNU Radio 3.7,
*maint-3.8* is compatible with GNU Radio 3.8, and *master* is compatible with
GNU Radio master, which tracks the development towards GNU Radio 3.9.
this an IEEE 802.11 a/g/p transceiver for GNU Radio v3.7. Over the air, I tested it with the Ettus USRP N210 with XCVR2450 and CBX daughterboards. For interoperability tests I use mainly an Atheros (ath5k) WiFi card. The code can also be used for packet error rate simulations.
# Installation # Installation
## Dependencies ## Dependencies
Please note that ```apt-get``` is the package manager of Debian/Ubuntu based systems, while ```port``` is one package manager for OSX. So use either (not both) according to your needs.
### GNU Radio
### log4cpp
I use the new [logging feature](http://gnuradio.org/doc/doxygen/page_logger.html) of GNU Radio which relies on log4cpp. This should be an optional dependency some day, but currently it is required. You can install it with
sudo apt-get install liblog4cpp5-dev
sudo port install log4cpp
### GNU Radio v3.7
You need at least version 3.7.3.
There are several ways to install GNU Radio. You can use There are several ways to install GNU Radio. You can use
- [pybombs](http://gnuradio.org/redmine/projects/pybombs/wiki) - [pybombs](http://gnuradio.org/redmine/projects/pybombs/wiki)
- [pre-combiled binaries](http://gnuradio.org/redmine/projects/gnuradio/wiki/BinaryPackages) - [pre-compiled binaries](http://gnuradio.org/redmine/projects/gnuradio/wiki/BinaryPackages)
- [from source](http://gnuradio.org/redmine/projects/gnuradio/wiki/InstallingGRFromSource) - [from source](http://gnuradio.org/redmine/projects/gnuradio/wiki/InstallingGRFromSource)
### IT++
I use the Viterbi decoder of IT++.
sudo apt-get install libitpp-dev
sudo port install itpp
### gr-foo ### gr-foo
I have some non project specific GNU Radio blocks in my gr-foo repo that are needed. For example the Wireshark connector. You can find these blocks at [https://github.com/bastibl/gr-foo](https://github.com/bastibl/gr-foo). They are installed with the typical command sequence: I have some non project specific GNU Radio blocks in my gr-foo repo that are
needed. For example the Wireshark connector. You can find these blocks at
[https://github.com/bastibl/gr-foo](https://github.com/bastibl/gr-foo). They are
installed with the typical command sequence:
git clone https://github.com/bastibl/gr-foo.git git clone https://github.com/bastibl/gr-foo.git
cd gr-foo cd gr-foo
@@ -65,48 +61,73 @@ To actually install the blocks do
sudo ldconfig sudo ldconfig
### Adjust Maximum Shared Memory ### Adjust Maximum Shared Memory
Since the transmitter is using the Tagged Stream blocks it has to store a complete frame in the buffer before processing it. The default maximum shared memory might not be enough on most Linux systems. It can be increased with Since the transmitter is using the Tagged Stream blocks it has to store a
complete frame in the buffer before processing it. The default maximum shared
memory might not be enough on most Linux systems. It can be increased with
sudo sysctl -w kernel.shmmax=2147483648 sudo sysctl -w kernel.shmmax=2147483648
### OFDM PHY ### OFDM PHY
The physical layer is encapsulated in a hierarchical block to allow for a clearer transceiver structure in GNU Radio Companion. This hierarchical block is not included in the installation process. You have to open ```/examples/wifi_phy_hier.grc``` with GNU Radio Companion and build it. This will install the block in ```~/.grc_gnuradio/```. The physical layer is encapsulated in a hierarchical block to allow for a
clearer transceiver structure in GNU Radio Companion. This hierarchical block is
not included in the installation process. You have to open
```/examples/wifi_phy_hier.grc``` with GNU Radio Companion and build it. This
will install the block in ```~/.grc_gnuradio/```.
### Check message port connections ### Check message port connections
Sometime the connections between the message ports (the gray ones in GNU Radio Companion) break. Therefore, please open the flow graphs and assert that everything is connected. It should be pretty obvious how the blocks are supposed to be wired. Actually this should not happen anymore, so if your ports are still unconnected please drop me a mail. Sometime the connections between the message ports (the gray ones in GNU Radio
Companion) break. Therefore, please open the flow graphs and assert that
everything is connected. It should be pretty obvious how the blocks are supposed
to be wired. Actually this should not happen anymore, so if your ports are still
unconnected please drop me a mail.
### Python OpenGL ### Python OpenGL
If you want to run the receive demo (the one that plots the subcarrier constellations), please assert that you have python-opengl installed. The nongl version of the plot does not work for me. If you want to run the receive demo (the one that plots the subcarrier
constellations), please assert that you have python-opengl installed. The nongl
version of the plot does not work for me.
### Run volk_profile ### Run volk_profile
volk_profile is part of GNU Radio. It benchmarks different SIMD implementations on your PC and creates a configuration file that stores the fastest version of every function. This can speed up the computation considerably and is required in order to deal with the high rate of incoming samples. volk_profile is part of GNU Radio. It benchmarks different SIMD implementations
on your PC and creates a configuration file that stores the fastest version of
every function. This can speed up the computation considerably and is required
in order to deal with the high rate of incoming samples.
### Calibrate your daughterboard ### Calibrate your daughterboard
If you have a WBX, SBX, or CBX daughterboard you should calibrate it in order to minimize IQ imbalance and TX DC offsets. See the [application notes](http://files.ettus.com/uhd_docs/manual/html/calibration.html). If you have a WBX, SBX, or CBX daughterboard you should calibrate it in order to
minimize IQ imbalance and TX DC offsets. See the [application
notes](http://files.ettus.com/manual/page_calibration.html).
# Checking your installation
# Checking you installation As a first step I recommend to test the ```wifi_loopback.grc``` flow graph. This
flow graph does not need any hardware and allows you to ensure that the software
part is installed correctly. So open the flow graph and run it. If everything
works as intended you should see some decoded packets on the console.
As a first step I recommend to test the ```wifi_loopback.grc``` flow graph. This flow graph does not need any hardware and allows you to ensure that the software part is installed correctly. So open the flow graph and run it. If everything works as intended you should see some decoded 'Hello World' packets in the console.
## Troubleshooting ## Troubleshooting
If GRC complains that it can't find some blocks (other than performance counters and hierarchical blocks) like If GRC complains that it can't find some blocks (other than performance counters
and hierarchical blocks) like
>>> Error: Block key "ieee802_11_ofdm_mac" not found in Platform - grc(GNU Radio Companion) >>> Error: Block key "ieee802_11_ofdm_mac" not found in Platform - grc(GNU Radio Companion)
>>> Error: Block key "foo_packet_pad" not found in Platform - grc(GNU Radio Companion) >>> Error: Block key "foo_packet_pad" not found in Platform - grc(GNU Radio Companion)
Most likely you used a different ```CMAKE_INSTALL_PREFIX``` for the module than for GNU Radio. Therefore, the blocks of the module ended up in a different directory and GRC can't find them. You have to tell GRC where these blocks are by creating/adding to your ```~/.gnuradio/config.conf``` something like Most likely you used a different ```CMAKE_INSTALL_PREFIX``` for the module than
for GNU Radio. Therefore, the blocks of the module ended up in a different
directory and GRC can't find them. You have to tell GRC where these blocks are
by creating/adding to your ```~/.gnuradio/config.conf``` something like
[grc] [grc]
global_blocks_path = /opt/local/share/gnuradio/grc/blocks global_blocks_path = /opt/local/share/gnuradio/grc/blocks
@@ -120,71 +141,69 @@ But with the directories that match your installation.
## Simulation ## Simulation
The loopback flow graph should give you an idea of how simulations can be conducted. To ease use, most blocks have debugging and logging capabilities that can generate traces of the simulation. You can read about the logging feature and how to use it on the [GNU Radio Wiki](http://gnuradio.org/doc/doxygen/page_logger.html). The loopback flow graph should give you an idea of how simulations can be
conducted. To ease use, most blocks have debugging and logging capabilities that
can generate traces of the simulation. You can read about the logging feature
and how to use it on the [GNU Radio
Wiki](http://gnuradio.org/doc/doxygen/page_logger.html).
## Unidirectional communication ## Unidirectional communication
As first over the air test I recommend to try ```wifi_rx.grc``` and ```wifi_tx.grc```. Just open the flow graphs in GNU Radio companion and execute them. If it does not work out of the box, try to play around with the gain. If everything works as intended you should see similar output as in the ```wifi_loopback.grc``` example. As first over the air test I recommend to try ```wifi_rx.grc``` and
```wifi_tx.grc```. Just open the flow graphs in GNU Radio companion and execute
them. If it does not work out of the box, try to play around with the gain. If
## RX frames from a WiFi card everything works as intended you should see similar output as in the
```wifi_loopback.grc``` example.
TBD
## TX frames to a WiFi card
TBD
## Transceiver (SDR <-> SDR)
TBD
## Ad Hoc Network with WiFi card ## Ad Hoc Network with WiFi card
- The transceiver is currently connected to a TAP device, i.e. is a virtual Ethernet interface. Therefore, we have no WiFi signaling like association requests and hence, the transceiver can not "join" an ad hoc network. You have to make some small changes to the kernel in order to convince you WiFi card to send to this hosts nevertheless. - The transceiver is currently connected to a TAP device, i.e. is a virtual
- The transceiver can not respond to ACKs in time. This is kind of an architectural limitation of USRP + GNU Radio since Ethernet and computations on a normal CPU introduce some latency. You can set the number of ACK retries to zero and handle retransmits on higher layers (-> TCP). Ethernet interface. Therefore, we have no WiFi signaling like association
- RTS/CTS is not working for the same reason. You can however just disable this mechanism. requests and hence, the transceiver can not "join" an ad hoc network. You have
- Currently, there is no CSMA/CA mechanism, but this can be implemented on the FPGA. to make some small changes to the kernel in order to convince you WiFi card to
send to this hosts nevertheless.
- The transceiver can not respond to ACKs in time. This is kind of an
architectural limitation of USRP + GNU Radio since Ethernet and computations
on a normal CPU introduce some latency. You can set the number of ACK retries
to zero and handle retransmits on higher layers (-> TCP).
- RTS/CTS is not working for the same reason. You can however just disable this
mechanism.
- Currently, there is no CSMA/CA mechanism, but this can be implemented on the
FPGA.
# Troubleshooting # Troubleshooting
- Please check compile and installation logs. They might contain interesting
information.
- Did you calibrate your daughterboard? - Did you calibrate your daughterboard?
- Did you run volk_profile? - Did you run volk_profile?
- Did you try different gain settings? - Did you try different gain settings?
- Did you close the case of the devices? - Did you close the case of the devices?
- Did you try real-time priority? - Did you try real-time priority?
- Did you compile GNU Radio and gr-ieee802-11 in release mode? - Did you compile GNU Radio and gr-ieee802-11 in release mode?
- If you see warnings that ```blocks_ctrlport_monitor_performance``` is missing that means that you installed GNU Radio without control port or performance counters. These blocks allow you to monitor the performance of the transceiver while it is running, but are not required. You can just delete them from the flow graph. - If you see warnings that ```blocks_ctrlport_monitor_performance``` is missing
that means that you installed GNU Radio without control port or performance
counters. These blocks allow you to monitor the performance of the transceiver
while it is running, but are not required. You can just delete them from the
flow graph.
- The message - The message
You must now use ifconfig to set its IP address. E.g., You must now use ifconfig to set its IP address. E.g.,
$ sudo ifconfig tap0 192.168.200.1 $ sudo ifconfig tap0 192.168.200.1
is normal and is output by the TUN/Tap Block during startup. The configuration of the TUN/TAP interface is handled by the scripts in the ```apps``` folder. is normal and is output by the TUN/Tap Block during startup. The configuration
- Did you try to tune the RF frequency out of the band of interest (i.e. used the LO offset menu of the flow graphs)? of the TUN/TAP interface is handled by the scripts in the ```apps``` folder.
- If 'D's appear, it might be related to your Ethernet card. Assert that you made the sysconf changes recommended by Ettus. Did you try to connect you PC directly to the USRP without a switch in between? - Did you try to tune the RF frequency out of the band of interest (i.e. used
the LO offset menu of the flow graphs)?
- If 'D's appear, it might be related to your Ethernet card. Assert that you
# Asking for help made the sysconf changes recommended by Ettus. Did you try to connect you PC
directly to the USRP without a switch in between?
In order to help you it is crucial that you provide enough information about what is going wrong and what you are actually trying to do. So if you write me please include at least the following
- OS (Ubuntu, OSX...)
- hardware (SDR and daughterboard)
- GNU Radio version
- What are you trying to do
- What is you setup, i.e. are you transmitting between SDRs or with WiFi cards.
- Bandwidth and frequency
- What did you already do to debug?
- Where exactly does it break, i.e. is frame detection working? Is the signal field decoded correctly?).
# Further information # Further information
For further information please checkout our project page For further information please checkout our project page
[http://www.ccs-labs.org/projects/wime/](http://www.ccs-labs.org/projects/wime/) [https://www.wime-project.net](https://www.wime-project.net)
-56
View File
@@ -1,56 +0,0 @@
#!/bin/bash
FILE="/tmp/ofdm.pcap"
FLOWGRAPH="rx_agc_demo.py"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
### create fifo
if [ -e ${FILE} ]
then
echo "${FILE}: file already exists"
if ! [ -p ${FILE} ]
then
echo "ERROR: ${FILE} exists and is not a FIFO"
exit 1
fi
else
echo "creating fifo: ${FILE}"
mkfifo ${FILE}
fi
### create tap interface
if [[ `ifconfig -a | grep tap0 | wc -l` -eq 0 ]]
then
sudo ip tuntap add dev tap0 user ${USER} mode tap
fi
### reconfigure it in any case, just to be sure it's up
sudo ifconfig tap0 down
sudo ifconfig tap0 hw ether 12:34:56:78:90:ab
sudo ifconfig tap0 up
sudo ifconfig tap0 192.168.123.1
### start transceiver
cd ${DIR}
cd ../examples/
./${FLOWGRAPH} &
sleep 1
### start wireshark
wireshark -k -i ${FILE} &
sleep 1
### start netcat
echo "##########################################################################"
echo "### starting netcat. Just type and the lines will be send to the flowgraph"
echo "##########################################################################"
sleep 2
#echo | nc -u localhost 52001
cat
+3 -1
View File
@@ -1,6 +1,8 @@
#!/bin/bash #!/bin/bash
FILE="/tmp/ofdm.pcap" ### Enable Wireshark Connector in wifi_rx flow graph
FILE="/tmp/wifi.pcap"
FLOWGRAPH="wifi_rx.py" FLOWGRAPH="wifi_rx.py"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+3
View File
@@ -15,6 +15,7 @@ PKG_CHECK_MODULES(PC_CPPUNIT "cppunit")
FIND_PATH(CPPUNIT_INCLUDE_DIRS FIND_PATH(CPPUNIT_INCLUDE_DIRS
NAMES cppunit/TestCase.h NAMES cppunit/TestCase.h
HINTS ${PC_CPPUNIT_INCLUDE_DIR} HINTS ${PC_CPPUNIT_INCLUDE_DIR}
${CMAKE_INSTALL_PREFIX}/include
PATHS PATHS
/usr/local/include /usr/local/include
/usr/include /usr/include
@@ -23,6 +24,8 @@ FIND_PATH(CPPUNIT_INCLUDE_DIRS
FIND_LIBRARY(CPPUNIT_LIBRARIES FIND_LIBRARY(CPPUNIT_LIBRARIES
NAMES cppunit NAMES cppunit
HINTS ${PC_CPPUNIT_LIBDIR} HINTS ${PC_CPPUNIT_LIBDIR}
${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
PATHS PATHS
${CPPUNIT_INCLUDE_DIRS}/../lib ${CPPUNIT_INCLUDE_DIRS}/../lib
/usr/local/lib /usr/local/lib
+36
View File
@@ -0,0 +1,36 @@
INCLUDE(FindPkgConfig)
PKG_CHECK_MODULES(PC_GNURADIO_RUNTIME gnuradio-runtime)
if(PC_GNURADIO_RUNTIME_FOUND)
# look for include files
FIND_PATH(
GNURADIO_RUNTIME_INCLUDE_DIRS
NAMES gnuradio/top_block.h
HINTS $ENV{GNURADIO_RUNTIME_DIR}/include
${PC_GNURADIO_RUNTIME_INCLUDE_DIRS}
${CMAKE_INSTALL_PREFIX}/include
PATHS /usr/local/include
/usr/include
)
# look for libs
FIND_LIBRARY(
GNURADIO_RUNTIME_LIBRARIES
NAMES gnuradio-runtime
HINTS $ENV{GNURADIO_RUNTIME_DIR}/lib
${PC_GNURADIO_RUNTIME_LIBDIR}
${CMAKE_INSTALL_PREFIX}/lib/
${CMAKE_INSTALL_PREFIX}/lib64/
PATHS /usr/local/lib
/usr/local/lib64
/usr/lib
/usr/lib64
)
set(GNURADIO_RUNTIME_FOUND ${PC_GNURADIO_RUNTIME_FOUND})
endif(PC_GNURADIO_RUNTIME_FOUND)
INCLUDE(FindPackageHandleStandardArgs)
# do not check GNURADIO_RUNTIME_INCLUDE_DIRS, is not set when default include path us used.
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_RUNTIME DEFAULT_MSG GNURADIO_RUNTIME_LIBRARIES)
MARK_AS_ADVANCED(GNURADIO_RUNTIME_LIBRARIES GNURADIO_RUNTIME_INCLUDE_DIRS)
-70
View File
@@ -1,70 +0,0 @@
# - Find ITPP
# Find the native ITPP includes and library
# This module defines
# ITPP_INCLUDE_DIR, where to find itpp/itbase.h, etc.
# ITPP_LIBRARIES, the libraries needed to use ITPP.
# ITPP_FOUND, If false, do not try to use ITPP.
# also defined, but not for general use are
# ITPP_LIBRARY, where to find the ITPP library.
include(FindPkgConfig)
pkg_check_modules(PC_ITPP itpp)
find_path(ITPP_INCLUDE_DIR
NAMES itpp/itbase.h
HINTS ${PC_ITPP_INCLUDEDIR}/include
${ITPP_DIR}/include
/usr/pkgs64/include
/usr/include
/usr/local/include
)
find_library(ITPP_LIBRARY_NORMAL
NAMES itpp
HINTS ${PC_ITPP_LIBDIR}
PATHS ${ITPP_DIR}/libs
"${ITPP_DIR}\\win32\\lib"
/usr/pkgs64/lib
/usr/lib64
/usr/lib
/usr/local/lib
)
find_library(ITPP_LIBRARY_DEBUG
NAMES itpp_debug
HINTS ${PC_ITPP_LIBDIR}
PATHS ${ITPP_DIR}/libs
"${ITPP_DIR}\\win32\\lib"
/usr/pkgs64/lib
/usr/lib64
/usr/lib
/usr/local/lib
)
if (ITPP_LIBRARY_NORMAL OR ITPP_LIBRARY_DEBUG)
if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ITPP_LIBRARY_DEBUG)
SET (ITPP_LIBRARY ${ITPP_LIBRARY_DEBUG})
else (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ITPP_LIBRARY_DEBUG)
SET (ITPP_LIBRARY ${ITPP_LIBRARY_NORMAL})
endif (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ITPP_LIBRARY_DEBUG)
endif (ITPP_LIBRARY_NORMAL OR ITPP_LIBRARY_DEBUG)
if (ITPP_LIBRARY AND ITPP_INCLUDE_DIR)
SET(ITPP_LIBRARIES ${ITPP_LIBRARY})
SET(ITPP_FOUND "YES")
else (ITPP_LIBRARY AND ITPP_INCLUDE_DIR)
SET(ITPP_FOUND "NO")
endif (ITPP_LIBRARY AND ITPP_INCLUDE_DIR)
if (ITPP_FOUND)
if (NOT ITPP_FIND_QUIETLY)
MESSAGE(STATUS "Found ITPP: ${ITPP_LIBRARIES}")
endif (NOT ITPP_FIND_QUIETLY)
else (ITPP_FOUND)
if (ITPP_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find ITPP library")
endif (ITPP_FIND_REQUIRED)
endif (ITPP_FOUND)
mark_as_advanced(
ITPP_LIBRARY
ITPP_INCLUDE_DIR
)
+7 -1
View File
@@ -94,7 +94,13 @@ macro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE flag have)
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG(${flag} ${have}) CHECK_CXX_COMPILER_FLAG(${flag} ${have})
if(${have}) if(${have})
add_definitions(${flag}) if(${CMAKE_VERSION} VERSION_GREATER "2.8.4")
STRING(FIND "${CMAKE_CXX_FLAGS}" "${flag}" flag_dup)
if(${flag_dup} EQUAL -1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
endif(${flag_dup} EQUAL -1)
endif(${CMAKE_VERSION} VERSION_GREATER "2.8.4")
endif(${have}) endif(${have})
endmacro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE) endmacro(GR_ADD_CXX_COMPILER_FLAG_IF_AVAILABLE)
+3 -3
View File
@@ -29,15 +29,15 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(LINUX TRUE) set(LINUX TRUE)
endif() endif()
if(LINUX AND EXISTS "/etc/debian_version") if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/debian_version")
set(DEBIAN TRUE) set(DEBIAN TRUE)
endif() endif()
if(LINUX AND EXISTS "/etc/redhat-release") if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/redhat-release")
set(REDHAT TRUE) set(REDHAT TRUE)
endif() endif()
if(LINUX AND EXISTS "/etc/slackware-version") if(NOT CMAKE_CROSSCOMPILING AND LINUX AND EXISTS "/etc/slackware-version")
set(SLACKWARE TRUE) set(SLACKWARE TRUE)
endif() endif()
+1 -2
View File
@@ -185,7 +185,6 @@ function(GR_PYTHON_INSTALL)
COMPONENT ${GR_PYTHON_INSTALL_COMPONENT} COMPONENT ${GR_PYTHON_INSTALL_COMPONENT}
) )
#################################################################### ####################################################################
elseif(GR_PYTHON_INSTALL_PROGRAMS) elseif(GR_PYTHON_INSTALL_PROGRAMS)
#################################################################### ####################################################################
@@ -207,7 +206,7 @@ function(GR_PYTHON_INSTALL)
add_custom_command( add_custom_command(
OUTPUT ${pyexefile} DEPENDS ${pyfile} OUTPUT ${pyexefile} DEPENDS ${pyfile}
COMMAND ${PYTHON_EXECUTABLE} -c COMMAND ${PYTHON_EXECUTABLE} -c
"open('${pyexefile}','w').write('\#!${pyexe_native}\\n'+open('${pyfile}').read())" "import re; R=re.compile('^\#!.*$\\n',flags=re.MULTILINE); open('${pyexefile}','w').write('\#!${pyexe_native}\\n'+R.sub('',open('${pyfile}','r').read()))"
COMMENT "Shebangin ${pyfile_name}" COMMENT "Shebangin ${pyfile_name}"
VERBATIM VERBATIM
) )
+6 -3
View File
@@ -39,7 +39,7 @@ function(GR_SWIG_MAKE_DOCS output_file)
set(input_files) set(input_files)
unset(INPUT_PATHS) unset(INPUT_PATHS)
foreach(input_path ${ARGN}) foreach(input_path ${ARGN})
if (IS_DIRECTORY ${input_path}) #when input path is a directory if(IS_DIRECTORY ${input_path}) #when input path is a directory
file(GLOB input_path_h_files ${input_path}/*.h) file(GLOB input_path_h_files ${input_path}/*.h)
else() #otherwise its just a file, no glob else() #otherwise its just a file, no glob
set(input_path_h_files ${input_path}) set(input_path_h_files ${input_path})
@@ -110,7 +110,7 @@ macro(GR_SWIG_MAKE name)
# vector<long unsigned int> (on 64-bit machines). Use this to test # vector<long unsigned int> (on 64-bit machines). Use this to test
# the size of size_t, then set SIZE_T_32 if it's a 32-bit machine # the size of size_t, then set SIZE_T_32 if it's a 32-bit machine
# or not if it's 64-bit. The logic in gr_type.i handles the rest. # or not if it's 64-bit. The logic in gr_type.i handles the rest.
INCLUDE (CheckTypeSize) INCLUDE(CheckTypeSize)
CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T) CHECK_TYPE_SIZE("size_t" SIZEOF_SIZE_T)
CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT) CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT)
if(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT}) if(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
@@ -118,7 +118,7 @@ macro(GR_SWIG_MAKE name)
endif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT}) endif(${SIZEOF_SIZE_T} EQUAL ${SIZEOF_UINT})
#do swig doc generation if specified #do swig doc generation if specified
if (GR_SWIG_DOC_FILE) if(GR_SWIG_DOC_FILE)
set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS}) set(GR_SWIG_DOCS_SOURCE_DEPS ${GR_SWIG_SOURCE_DEPS})
list(APPEND GR_SWIG_DOCS_TARGET_DEPS ${GR_SWIG_TARGET_DEPS}) list(APPEND GR_SWIG_DOCS_TARGET_DEPS ${GR_SWIG_TARGET_DEPS})
GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS}) GR_SWIG_MAKE_DOCS(${GR_SWIG_DOC_FILE} ${GR_SWIG_DOC_DIRS})
@@ -172,6 +172,9 @@ macro(GR_SWIG_MAKE name)
include(UseSWIG) include(UseSWIG)
SWIG_ADD_MODULE(${name} python ${ifiles}) SWIG_ADD_MODULE(${name} python ${ifiles})
SWIG_LINK_LIBRARIES(${name} ${PYTHON_LIBRARIES} ${GR_SWIG_LIBRARIES}) SWIG_LINK_LIBRARIES(${name} ${PYTHON_LIBRARIES} ${GR_SWIG_LIBRARIES})
if(${name} STREQUAL "runtime_swig")
SET_TARGET_PROPERTIES(${SWIG_MODULE_runtime_swig_REAL_NAME} PROPERTIES DEFINE_SYMBOL "gnuradio_runtime_EXPORTS")
endif(${name} STREQUAL "runtime_swig")
endmacro(GR_SWIG_MAKE) endmacro(GR_SWIG_MAKE)
+304
View File
@@ -0,0 +1,304 @@
# - SWIG module for CMake
# Defines the following macros:
# SWIG_ADD_MODULE(name language [ files ])
# - Define swig module with given name and specified language
# SWIG_LINK_LIBRARIES(name [ libraries ])
# - Link libraries to swig module
# All other macros are for internal use only.
# To get the actual name of the swig module,
# use: ${SWIG_MODULE_${name}_REAL_NAME}.
# Set Source files properties such as CPLUSPLUS and SWIG_FLAGS to specify
# special behavior of SWIG. Also global CMAKE_SWIG_FLAGS can be used to add
# special flags to all swig calls.
# Another special variable is CMAKE_SWIG_OUTDIR, it allows one to specify
# where to write all the swig generated module (swig -outdir option)
# The name-specific variable SWIG_MODULE_<name>_EXTRA_DEPS may be used
# to specify extra dependencies for the generated modules.
# If the source file generated by swig need some special flag you can use
# set_source_files_properties( ${swig_generated_file_fullname}
# PROPERTIES COMPILE_FLAGS "-bla")
#=============================================================================
# Copyright 2004-2009 Kitware, Inc.
# Copyright 2009 Mathieu Malaterre <mathieu.malaterre@gmail.com>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
set(SWIG_CXX_EXTENSION "cxx")
set(SWIG_EXTRA_LIBRARIES "")
set(SWIG_PYTHON_EXTRA_FILE_EXTENSION "py")
#
# For given swig module initialize variables associated with it
#
macro(SWIG_MODULE_INITIALIZE name language)
string(TOUPPER "${language}" swig_uppercase_language)
string(TOLOWER "${language}" swig_lowercase_language)
set(SWIG_MODULE_${name}_LANGUAGE "${swig_uppercase_language}")
set(SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG "${swig_lowercase_language}")
set(SWIG_MODULE_${name}_REAL_NAME "${name}")
if("${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "UNKNOWN")
message(FATAL_ERROR "SWIG Error: Language \"${language}\" not found")
elseif("${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "PYTHON")
# when swig is used without the -interface it will produce in the module.py
# a 'import _modulename' statement, which implies having a corresponding
# _modulename.so (*NIX), _modulename.pyd (Win32).
set(SWIG_MODULE_${name}_REAL_NAME "_${name}")
elseif("${SWIG_MODULE_${name}_LANGUAGE}" STREQUAL "PERL")
set(SWIG_MODULE_${name}_EXTRA_FLAGS "-shadow")
endif()
endmacro()
#
# For a given language, input file, and output file, determine extra files that
# will be generated. This is internal swig macro.
#
macro(SWIG_GET_EXTRA_OUTPUT_FILES language outfiles generatedpath infile)
set(${outfiles} "")
get_source_file_property(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename
${infile} SWIG_MODULE_NAME)
if(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename STREQUAL "NOTFOUND")
get_filename_component(SWIG_GET_EXTRA_OUTPUT_FILES_module_basename "${infile}" NAME_WE)
endif()
foreach(it ${SWIG_${language}_EXTRA_FILE_EXTENSION})
set(${outfiles} ${${outfiles}}
"${generatedpath}/${SWIG_GET_EXTRA_OUTPUT_FILES_module_basename}.${it}")
endforeach()
endmacro()
#
# Take swig (*.i) file and add proper custom commands for it
#
macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile)
set(swig_full_infile ${infile})
get_filename_component(swig_source_file_path "${infile}" PATH)
get_filename_component(swig_source_file_name_we "${infile}" NAME_WE)
get_source_file_property(swig_source_file_generated ${infile} GENERATED)
get_source_file_property(swig_source_file_cplusplus ${infile} CPLUSPLUS)
get_source_file_property(swig_source_file_flags ${infile} SWIG_FLAGS)
if("${swig_source_file_flags}" STREQUAL "NOTFOUND")
set(swig_source_file_flags "")
endif()
set(swig_source_file_fullname "${infile}")
if(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_SOURCE_DIR}")
string(REGEX REPLACE
"^${CMAKE_CURRENT_SOURCE_DIR}" ""
swig_source_file_relative_path
"${swig_source_file_path}")
else()
if(${swig_source_file_path} MATCHES "^${CMAKE_CURRENT_BINARY_DIR}")
string(REGEX REPLACE
"^${CMAKE_CURRENT_BINARY_DIR}" ""
swig_source_file_relative_path
"${swig_source_file_path}")
set(swig_source_file_generated 1)
else()
set(swig_source_file_relative_path "${swig_source_file_path}")
if(swig_source_file_generated)
set(swig_source_file_fullname "${CMAKE_CURRENT_BINARY_DIR}/${infile}")
else()
set(swig_source_file_fullname "${CMAKE_CURRENT_SOURCE_DIR}/${infile}")
endif()
endif()
endif()
set(swig_generated_file_fullname
"${CMAKE_CURRENT_BINARY_DIR}")
if(swig_source_file_relative_path)
set(swig_generated_file_fullname
"${swig_generated_file_fullname}/${swig_source_file_relative_path}")
endif()
# If CMAKE_SWIG_OUTDIR was specified then pass it to -outdir
if(CMAKE_SWIG_OUTDIR)
set(swig_outdir ${CMAKE_SWIG_OUTDIR})
else()
set(swig_outdir ${CMAKE_CURRENT_BINARY_DIR})
endif()
SWIG_GET_EXTRA_OUTPUT_FILES(${SWIG_MODULE_${name}_LANGUAGE}
swig_extra_generated_files
"${swig_outdir}"
"${infile}")
set(swig_generated_file_fullname
"${swig_generated_file_fullname}/${swig_source_file_name_we}")
# add the language into the name of the file (i.e. TCL_wrap)
# this allows for the same .i file to be wrapped into different languages
set(swig_generated_file_fullname
"${swig_generated_file_fullname}${SWIG_MODULE_${name}_LANGUAGE}_wrap")
if(swig_source_file_cplusplus)
set(swig_generated_file_fullname
"${swig_generated_file_fullname}.${SWIG_CXX_EXTENSION}")
else()
set(swig_generated_file_fullname
"${swig_generated_file_fullname}.c")
endif()
# Shut up some warnings from poor SWIG code generation that we
# can do nothing about, when this flag is available
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag("-Wno-unused-but-set-variable" HAVE_WNO_UNUSED_BUT_SET_VARIABLE)
if(HAVE_WNO_UNUSED_BUT_SET_VARIABLE)
set_source_files_properties(${swig_generated_file_fullname}
PROPERTIES COMPILE_FLAGS "-Wno-unused-but-set-variable")
endif(HAVE_WNO_UNUSED_BUT_SET_VARIABLE)
get_directory_property(cmake_include_directories INCLUDE_DIRECTORIES)
set(swig_include_dirs)
foreach(it ${cmake_include_directories})
set(swig_include_dirs ${swig_include_dirs} "-I${it}")
endforeach()
set(swig_special_flags)
# default is c, so add c++ flag if it is c++
if(swig_source_file_cplusplus)
set(swig_special_flags ${swig_special_flags} "-c++")
endif()
set(swig_extra_flags)
if(SWIG_MODULE_${name}_EXTRA_FLAGS)
set(swig_extra_flags ${swig_extra_flags} ${SWIG_MODULE_${name}_EXTRA_FLAGS})
endif()
# hack to work around CMake bug in add_custom_command with multiple OUTPUT files
file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib
unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5]
print(re.sub('\\W', '_', '${name} ${reldir} ' + unique))"
OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE
)
file(
WRITE ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp.in
"int main(void){return 0;}\n"
)
# create dummy dependencies
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp.in
${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp
DEPENDS "${swig_source_file_fullname}" ${SWIG_MODULE_${name}_EXTRA_DEPS}
COMMENT ""
)
# create the dummy target
add_executable(${_target} ${CMAKE_CURRENT_BINARY_DIR}/${_target}.cpp)
# add a custom command to the dummy target
add_custom_command(
TARGET ${_target}
# Let's create the ${swig_outdir} at execution time, in case dir contains $(OutDir)
COMMAND ${CMAKE_COMMAND} -E make_directory ${swig_outdir}
COMMAND "${SWIG_EXECUTABLE}"
ARGS "-${SWIG_MODULE_${name}_SWIG_LANGUAGE_FLAG}"
${swig_source_file_flags}
${CMAKE_SWIG_FLAGS}
-outdir ${swig_outdir}
${swig_special_flags}
${swig_extra_flags}
${swig_include_dirs}
-o "${swig_generated_file_fullname}"
"${swig_source_file_fullname}"
COMMENT "Swig source"
)
#add dummy independent dependencies from the _target to each file
#that will be generated by the SWIG command above
set(${outfiles} "${swig_generated_file_fullname}" ${swig_extra_generated_files})
foreach(swig_gen_file ${${outfiles}})
add_custom_command(
OUTPUT ${swig_gen_file}
COMMAND ""
DEPENDS ${_target}
COMMENT ""
)
endforeach()
set_source_files_properties(
${outfiles} PROPERTIES GENERATED 1
)
endmacro()
#
# Create Swig module
#
macro(SWIG_ADD_MODULE name language)
SWIG_MODULE_INITIALIZE(${name} ${language})
set(swig_dot_i_sources)
set(swig_other_sources)
foreach(it ${ARGN})
if(${it} MATCHES ".*\\.i$")
set(swig_dot_i_sources ${swig_dot_i_sources} "${it}")
else()
set(swig_other_sources ${swig_other_sources} "${it}")
endif()
endforeach()
set(swig_generated_sources)
foreach(it ${swig_dot_i_sources})
SWIG_ADD_SOURCE_TO_MODULE(${name} swig_generated_source ${it})
set(swig_generated_sources ${swig_generated_sources} "${swig_generated_source}")
endforeach()
get_directory_property(swig_extra_clean_files ADDITIONAL_MAKE_CLEAN_FILES)
set_directory_properties(PROPERTIES
ADDITIONAL_MAKE_CLEAN_FILES "${swig_extra_clean_files};${swig_generated_sources}")
add_library(${SWIG_MODULE_${name}_REAL_NAME}
MODULE
${swig_generated_sources}
${swig_other_sources})
string(TOLOWER "${language}" swig_lowercase_language)
if ("${swig_lowercase_language}" STREQUAL "java")
if (APPLE)
# In java you want:
# System.loadLibrary("LIBRARY");
# then JNI will look for a library whose name is platform dependent, namely
# MacOS : libLIBRARY.jnilib
# Windows: LIBRARY.dll
# Linux : libLIBRARY.so
set_target_properties (${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".jnilib")
endif ()
endif ()
if ("${swig_lowercase_language}" STREQUAL "python")
# this is only needed for the python case where a _modulename.so is generated
set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES PREFIX "")
# Python extension modules on Windows must have the extension ".pyd"
# instead of ".dll" as of Python 2.5. Older python versions do support
# this suffix.
# http://docs.python.org/whatsnew/ports.html#SECTION0001510000000000000000
# <quote>
# Windows: .dll is no longer supported as a filename extension for extension modules.
# .pyd is now the only filename extension that will be searched for.
# </quote>
if(WIN32 AND NOT CYGWIN)
set_target_properties(${SWIG_MODULE_${name}_REAL_NAME} PROPERTIES SUFFIX ".pyd")
endif()
endif ()
endmacro()
#
# Like TARGET_LINK_LIBRARIES but for swig modules
#
macro(SWIG_LINK_LIBRARIES name)
if(SWIG_MODULE_${name}_REAL_NAME)
target_link_libraries(${SWIG_MODULE_${name}_REAL_NAME} ${ARGN})
else()
message(SEND_ERROR "Cannot find Swig library \"${name}\".")
endif()
endmacro()
+1599 -1014
View File
File diff suppressed because it is too large Load Diff
+1447 -1424
View File
File diff suppressed because it is too large Load Diff
+2857 -1887
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+3447 -2312
View File
File diff suppressed because it is too large Load Diff
+1444 -1407
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -2,7 +2,7 @@
<block> <block>
<name>Chunks to Symbols</name> <name>Chunks to Symbols</name>
<key>ieee802_11_chunks_to_symbols_xx</key> <key>ieee802_11_chunks_to_symbols_xx</key>
<category>IEEE802.11</category> <category>[IEEE802.11]</category>
<import>import ieee802_11</import> <import>import ieee802_11</import>
<make>ieee802_11.chunks_to_symbols()</make> <make>ieee802_11.chunks_to_symbols()</make>
<sink> <sink>
@@ -1,11 +1,11 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<block> <block>
<name>OFDM Decode MAC</name> <name>WiFi Decode MAC</name>
<key>ieee802_11_ofdm_decode_mac</key> <key>ieee802_11_decode_mac</key>
<category>IEEE802.11</category> <category>[IEEE802.11]</category>
<import>import ieee802_11</import> <import>import ieee802_11</import>
<make>ieee802_11.ofdm_decode_mac($log, $debug)</make> <make>ieee802_11.decode_mac($log, $debug)</make>
<param> <param>
<name>Log</name> <name>Log</name>
@@ -41,14 +41,14 @@
<sink> <sink>
<name>in</name> <name>in</name>
<type>complex</type> <type>byte</type>
<vlen>48</vlen> <vlen>48</vlen>
<nports>1</nports>
</sink> </sink>
<source> <source>
<name>out</name> <name>out</name>
<type>message</type> <type>message</type>
<optional>1</optional>
</source> </source>
</block> </block>
+1 -1
View File
@@ -3,7 +3,7 @@
<block> <block>
<name>Ethernet Encapsulation</name> <name>Ethernet Encapsulation</name>
<key>ieee802_11_ether_encap</key> <key>ieee802_11_ether_encap</key>
<category>IEEE802.11</category> <category>[IEEE802.11]</category>
<import>import ieee802_11</import> <import>import ieee802_11</import>
<make>ieee802_11.ether_encap($debug)</make> <make>ieee802_11.ether_encap($debug)</make>
+105
View File
@@ -0,0 +1,105 @@
<?xml version="1.0"?>
<block>
<name>WiFi Frame Equalizer</name>
<key>ieee802_11_frame_equalizer</key>
<category>[IEEE802.11]</category>
<import>import ieee802_11</import>
<make>ieee802_11.frame_equalizer($algo, $freq, $bw, $log, $debug)</make>
<callback>set_algorithm($algo)</callback>
<callback>set_frequency($freq)</callback>
<callback>set_bandwidth($bw)</callback>
<param>
<name>Algorithm</name>
<key>algo</key>
<value>ieee802_11.LS</value>
<type>int</type>
<option>
<name>LS</name>
<key>ieee802_11.LS</key>
</option>
<option>
<name>LMS</name>
<key>ieee802_11.LMS</key>
</option>
<option>
<name>Comb</name>
<key>ieee802_11.COMB</key>
</option>
<option>
<name>STA</name>
<key>ieee802_11.STA</key>
</option>
</param>
<param>
<name>Frequency</name>
<key>freq</key>
<value>5.89e9</value>
<type>real</type>
</param>
<param>
<name>Bandwidth</name>
<key>bw</key>
<value>10e6</value>
<type>real</type>
</param>
<param>
<name>Log</name>
<key>log</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<sink>
<name>in</name>
<type>complex</type>
<vlen>64</vlen>
<nports>1</nports>
</sink>
<source>
<name>out</name>
<type>byte</type>
<vlen>48</vlen>
<nports>1</nports>
</source>
<source>
<name>symbols</name>
<type>message</type>
<optional>1</optional>
</source>
</block>
@@ -1,11 +1,11 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<block> <block>
<name>OFDM MAC</name> <name>WiFi MAC</name>
<key>ieee802_11_ofdm_mac</key> <key>ieee802_11_mac</key>
<category>IEEE802.11</category> <category>[IEEE802.11]</category>
<import>import ieee802_11</import> <import>import ieee802_11</import>
<make>ieee802_11.ofdm_mac($src_mac, $dst_mac, $bss_mac)</make> <make>ieee802_11.mac($src_mac, $dst_mac, $bss_mac)</make>
<param> <param>
<name>SRC MAC</name> <name>SRC MAC</name>
@@ -1,11 +1,11 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<block> <block>
<name>OFDM Mapper</name> <name>WiFi Mapper</name>
<key>ieee802_11_ofdm_mapper</key> <key>ieee802_11_mapper</key>
<category>IEEE802.11</category> <category>[IEEE802.11]</category>
<import>import ieee802_11</import> <import>import ieee802_11</import>
<make>ieee802_11.ofdm_mapper($encoding, $debug)</make> <make>ieee802_11.mapper($encoding, $debug)</make>
<callback>set_encoding($encoding)</callback> <callback>set_encoding($encoding)</callback>
<param> <param>
+1 -1
View File
@@ -2,7 +2,7 @@
<block> <block>
<name>Moving Average</name> <name>Moving Average</name>
<key>ieee802_11_moving_average_xx</key> <key>ieee802_11_moving_average_xx</key>
<category>IEEE802.11</category> <category>[IEEE802.11]</category>
<import>import ieee802_11</import> <import>import ieee802_11</import>
<make>ieee802_11.moving_average_$(type.fcn)($length)</make> <make>ieee802_11.moving_average_$(type.fcn)($length)</make>
<callback>set_length($length)</callback> <callback>set_length($length)</callback>
-58
View File
@@ -1,58 +0,0 @@
<?xml version="1.0"?>
<block>
<name>OFDM Decode Signal</name>
<key>ieee802_11_ofdm_decode_signal</key>
<category>IEEE802.11</category>
<import>import ieee802_11</import>
<make>ieee802_11.ofdm_decode_signal($log, $debug)</make>
<param>
<name>Log</name>
<key>log</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<sink>
<name>in</name>
<type>complex</type>
<vlen>48</vlen>
<nports>1</nports>
</sink>
<source>
<name>out</name>
<type>complex</type>
<vlen>48</vlen>
<nports>1</nports>
</source>
</block>
-58
View File
@@ -1,58 +0,0 @@
<?xml version="1.0"?>
<block>
<name>OFDM Equalize Symbols</name>
<key>ieee802_11_ofdm_equalize_symbols</key>
<category>IEEE802.11</category>
<import>import ieee802_11</import>
<make>ieee802_11.ofdm_equalize_symbols($algo, $debug)</make>
<callback>set_algorithm($algo)</callback>
<param>
<name>Algorithm</name>
<key>algo</key>
<value>ieee802_11.LINEAR_COMB</value>
<type>int</type>
<option>
<name>LMS</name>
<key>ieee802_11.LMS</key>
</option>
<option>
<name>linear comb</name>
<key>ieee802_11.LINEAR_COMB</key>
</option>
</param>
<param>
<name>Debug</name>
<key>debug</key>
<value>False</value>
<type>bool</type>
<option>
<name>Enable</name>
<key>True</key>
</option>
<option>
<name>Disable</name>
<key>False</key>
</option>
</param>
<sink>
<name>in</name>
<type>complex</type>
<vlen>64</vlen>
<nports>1</nports>
</sink>
<source>
<name>out</name>
<type>complex</type>
<vlen>48</vlen>
<nports>1</nports>
</source>
</block>
@@ -1,11 +1,11 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<block> <block>
<name>OFDM Parse MAC</name> <name>WiFi Parse MAC</name>
<key>ieee802_11_ofdm_parse_mac</key> <key>ieee802_11_parse_mac</key>
<category>IEEE802.11</category> <category>[IEEE802.11]</category>
<import>import ieee802_11</import> <import>import ieee802_11</import>
<make>ieee802_11.ofdm_parse_mac($log, $debug)</make> <make>ieee802_11.parse_mac($log, $debug)</make>
<param> <param>
<name>Log</name> <name>Log</name>
@@ -1,11 +1,11 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<block> <block>
<name>OFDM Sync Long</name> <name>WiFi Sync Long</name>
<key>ieee802_11_ofdm_sync_long</key> <key>ieee802_11_sync_long</key>
<category>IEEE802.11</category> <category>[IEEE802.11]</category>
<import>import ieee802_11</import> <import>import ieee802_11</import>
<make>ieee802_11.ofdm_sync_long($sync_length, $log, $debug)</make> <make>ieee802_11.sync_long($sync_length, $log, $debug)</make>
<param> <param>
<name>Log</name> <name>Log</name>
@@ -1,11 +1,11 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<block> <block>
<name>OFDM Sync Short</name> <name>WiFi Sync Short</name>
<key>ieee802_11_ofdm_sync_short</key> <key>ieee802_11_sync_short</key>
<category>IEEE802.11</category> <category>[IEEE802.11]</category>
<import>import ieee802_11</import> <import>import ieee802_11</import>
<make>ieee802_11.ofdm_sync_short($threshold, $min_plateau, $log, $debug)</make> <make>ieee802_11.sync_short($threshold, $min_plateau, $log, $debug)</make>
<param> <param>
<name>Log</name> <name>Log</name>
-37
View File
@@ -1,37 +0,0 @@
<?xml version="1.0"?>
<block>
<name>WiFi EDCA</name>
<key>ieee802_11_wifi_edca</key>
<category>IEEE802.11</category>
<import>import ieee802_11</import>
<make>ieee802_11.wifi_edca($cw_min, $aifsn)</make>
<param>
<name>CW min</name>
<key>cw_min</key>
<value>[15, 15, 7, 3]</value>
<type>int_vector</type>
</param>
<param>
<name>AIFSN [slots]</name>
<key>aifsn</key>
<value>[9, 6, 3, 2]</value>
<type>int_vector</type>
</param>
<check>len($cw_min) == len($aifsn)</check>
<sink>
<name>ac in</name>
<type>message</type>
<nports>len($cw_min)</nports>
<optional>1</optional>
</sink>
<source>
<name>mac out</name>
<type>message</type>
</source>
</block>
+10 -11
View File
@@ -1,5 +1,5 @@
# #
# Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> # Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -70,17 +70,16 @@ list(APPEND include_sources
${generated_includes} ${generated_includes}
api.h api.h
chunks_to_symbols.h chunks_to_symbols.h
constellations.h
decode_mac.h
ether_encap.h ether_encap.h
ofdm_decode_mac.h frame_equalizer.h
ofdm_decode_signal.h mac.h
ofdm_equalize_symbols.h mapper.h
ofdm_mac.h parse_mac.h
ofdm_mapper.h signal_field.h
ofdm_parse_mac.h sync_long.h
ofdm_sync_long.h sync_short.h
ofdm_sync_short.h
wifi_edca.h
wifi_signal_field.h
) )
install( install(
+1 -1
View File
@@ -22,7 +22,7 @@
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
class IEEE802_11_API chunks_to_symbols : virtual public tagged_stream_block class IEEE802_11_API chunks_to_symbols : virtual public tagged_stream_block
{ {
public: public:
+71
View File
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2016 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_IEEE802_11_CONSTELLATIONS_H
#define INCLUDED_IEEE802_11_CONSTELLATIONS_H
#include <ieee802-11/api.h>
#include <gnuradio/digital/constellation.h>
namespace gr {
namespace ieee802_11 {
class IEEE802_11_API constellation_bpsk : virtual public digital::constellation
{
public:
typedef boost::shared_ptr<gr::ieee802_11::constellation_bpsk> sptr;
static sptr make();
protected:
constellation_bpsk();
};
class IEEE802_11_API constellation_qpsk : virtual public digital::constellation
{
public:
typedef boost::shared_ptr<gr::ieee802_11::constellation_qpsk> sptr;
static sptr make();
protected:
constellation_qpsk();
};
class IEEE802_11_API constellation_16qam : virtual public digital::constellation
{
public:
typedef boost::shared_ptr<gr::ieee802_11::constellation_16qam> sptr;
static sptr make();
protected:
constellation_16qam();
};
class IEEE802_11_API constellation_64qam : virtual public digital::constellation
{
public:
typedef boost::shared_ptr<gr::ieee802_11::constellation_64qam> sptr;
static sptr make();
protected:
constellation_64qam();
};
} // namespace ieee802_11
} // namespace gr
#endif /* INCLUDED_IEEE802_11_CONSTELLATIONS_H */
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_OFDM_PARSE_MAC_H #ifndef INCLUDED_IEEE802_11_DECODE_MAC_H
#define INCLUDED_IEEE802_11_OFDM_PARSE_MAC_H #define INCLUDED_IEEE802_11_DECODE_MAC_H
#include <ieee802-11/api.h> #include <ieee802-11/api.h>
#include <gnuradio/block.h> #include <gnuradio/block.h>
@@ -23,11 +23,11 @@
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
class IEEE802_11_API ofdm_parse_mac : virtual public block class IEEE802_11_API decode_mac : virtual public block
{ {
public: public:
typedef boost::shared_ptr<ofdm_parse_mac> sptr; typedef boost::shared_ptr<decode_mac> sptr;
static sptr make(bool log = false, bool debug = false); static sptr make(bool log = false, bool debug = false);
}; };
@@ -35,4 +35,6 @@ public:
} // namespace ieee802_11 } // namespace ieee802_11
} // namespace gr } // namespace gr
#endif /* INCLUDED_IEEE802_11_OFDM_PARSE_MAC_H */ #endif /* INCLUDED_IEEE802_11_DECODE_MAC_H */
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013, 2015 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -13,33 +13,39 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/ */
#ifndef INCLUDED_IEEE802_11_OFDM_EQUALIZE_SYMBOLS_H
#define INCLUDED_IEEE802_11_OFDM_EQUALIZE_SYMBOLS_H
#ifndef INCLUDED_IEEE802_11_FRAME_EQUALIZER_H
#define INCLUDED_IEEE802_11_FRAME_EQUALIZER_H
#include <ieee802-11/api.h> #include <ieee802-11/api.h>
#include <gnuradio/block.h> #include <gnuradio/block.h>
enum Equalizer { enum Equalizer {
LMS = 0, LS = 0,
LINEAR_COMB = 1, LMS = 1,
COMB = 2,
STA = 3,
}; };
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
class IEEE802_11_API ofdm_equalize_symbols : virtual public block class IEEE802_11_API frame_equalizer : virtual public gr::block
{ {
public: public:
typedef boost::shared_ptr<frame_equalizer> sptr;
typedef boost::shared_ptr<ofdm_equalize_symbols> sptr; static sptr make(Equalizer algo, double freq, double bw,
static sptr make(Equalizer algo, bool debug = false); bool log, bool debug);
virtual void set_algorithm(Equalizer algo) = 0; virtual void set_algorithm(Equalizer algo) = 0;
virtual void set_bandwidth(double bw) = 0;
virtual void set_frequency(double freq) = 0;
}; };
} // namespace ieee802_11 } // namespace ieee802_11
} // namespace gr } // namespace gr
#endif /* INCLUDED_IEEE802_11_OFDM_EQUALIZE_SYMBOLS_H*/
#endif /* INCLUDED_IEEE802_11_FRAME_EQUALIZER_H */
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_OFDM_MAC_H #ifndef INCLUDED_IEEE802_11_MAC_H
#define INCLUDED_IEEE802_11_OFDM_MAC_H #define INCLUDED_IEEE802_11_MAC_H
#include <ieee802-11/api.h> #include <ieee802-11/api.h>
#include <gnuradio/block.h> #include <gnuradio/block.h>
@@ -23,11 +23,11 @@
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
class IEEE802_11_API ofdm_mac : virtual public block class IEEE802_11_API mac : virtual public block
{ {
public: public:
typedef boost::shared_ptr<ofdm_mac> sptr; typedef boost::shared_ptr<mac> sptr;
static sptr make(std::vector<uint8_t> src_mac, static sptr make(std::vector<uint8_t> src_mac,
std::vector<uint8_t> dst_mac, std::vector<uint8_t> dst_mac,
std::vector<uint8_t> bss_mac); std::vector<uint8_t> bss_mac);
@@ -36,4 +36,4 @@ public:
} // namespace ieee802_11 } // namespace ieee802_11
} // namespace gr } // namespace gr
#endif /* INCLUDED_IEEE802_11_OFDM_MAC_H */ #endif /* INCLUDED_IEEE802_11_MAC_H */
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_OFDM_MAPPER_H #ifndef INCLUDED_IEEE802_11_MAPPER_H
#define INCLUDED_IEEE802_11_OFDM_MAPPER_H #define INCLUDED_IEEE802_11_MAPPER_H
#include <ieee802-11/api.h> #include <ieee802-11/api.h>
#include <gnuradio/block.h> #include <gnuradio/block.h>
@@ -34,11 +34,11 @@ enum Encoding {
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
class IEEE802_11_API ofdm_mapper : virtual public block class IEEE802_11_API mapper : virtual public block
{ {
public: public:
typedef boost::shared_ptr<ofdm_mapper> sptr; typedef boost::shared_ptr<mapper> sptr;
static sptr make(Encoding mcs, bool debug = false); static sptr make(Encoding mcs, bool debug = false);
virtual void set_encoding(Encoding mcs) = 0; virtual void set_encoding(Encoding mcs) = 0;
}; };
@@ -46,4 +46,4 @@ public:
} // namespace ieee802_11 } // namespace ieee802_11
} // namespace gr } // namespace gr
#endif /* INCLUDED_IEEE802_11_OFDM_MAPPER_H */ #endif /* INCLUDED_IEEE802_11_MAPPER_H */
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_OFDM_DECODE_MAC_H #ifndef INCLUDED_IEEE802_11_PARSE_MAC_H
#define INCLUDED_IEEE802_11_OFDM_DECODE_MAC_H #define INCLUDED_IEEE802_11_PARSE_MAC_H
#include <ieee802-11/api.h> #include <ieee802-11/api.h>
#include <gnuradio/block.h> #include <gnuradio/block.h>
@@ -23,18 +23,16 @@
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
class IEEE802_11_API ofdm_decode_mac : virtual public block class IEEE802_11_API parse_mac : virtual public block
{ {
public: public:
typedef boost::shared_ptr<ofdm_decode_mac> sptr; typedef boost::shared_ptr<parse_mac> sptr;
static sptr make(bool log = false, bool debug = false); static sptr make(bool log = false, bool debug = false);
}; };
} // namespace ieee802_11 } // namespace ieee802_11
} // namespace gr } // namespace gr
#endif /* INCLUDED_IEEE802_11_OFDM_DECODE_MAC_H */
#endif /* INCLUDED_IEEE802_11_PARSE_MAC_H */
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -15,8 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_WIFI_SIGNAL_FIELD_H #ifndef INCLUDED_IEEE802_11_SIGNAL_FIELD_H
#define INCLUDED_IEEE802_11_WIFI_SIGNAL_FIELD_H #define INCLUDED_IEEE802_11_SIGNAL_FIELD_H
#include <ieee802-11/api.h> #include <ieee802-11/api.h>
#include <gnuradio/digital/packet_header_default.h> #include <gnuradio/digital/packet_header_default.h>
@@ -24,18 +24,18 @@
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
class IEEE802_11_API wifi_signal_field : virtual public digital::packet_header_default class IEEE802_11_API signal_field : virtual public digital::packet_header_default
{ {
public: public:
typedef boost::shared_ptr<wifi_signal_field> sptr; typedef boost::shared_ptr<signal_field> sptr;
static sptr make(); static sptr make();
protected: protected:
wifi_signal_field(); signal_field();
}; };
} // namespace ieee802_11 } // namespace ieee802_11
} // namespace gr } // namespace gr
#endif /* INCLUDED_IEEE802_11_WIFI_SIGNAL_FIELD_H */ #endif /* INCLUDED_IEEE802_11_SIGNAL_FIELD_H */
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_OFDM_SYNC_LONG_H #ifndef INCLUDED_IEEE802_11_SYNC_LONG_H
#define INCLUDED_IEEE802_11_OFDM_SYNC_LONG_H #define INCLUDED_IEEE802_11_SYNC_LONG_H
#include <ieee802-11/api.h> #include <ieee802-11/api.h>
#include <gnuradio/block.h> #include <gnuradio/block.h>
@@ -23,11 +23,11 @@
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
class IEEE802_11_API ofdm_sync_long : virtual public block class IEEE802_11_API sync_long : virtual public block
{ {
public: public:
typedef boost::shared_ptr<ofdm_sync_long> sptr; typedef boost::shared_ptr<sync_long> sptr;
static sptr make(unsigned int sync_length, static sptr make(unsigned int sync_length,
bool log = false, bool debug = false); bool log = false, bool debug = false);
@@ -36,4 +36,4 @@ public:
} // namespace ieee802_11 } // namespace ieee802_11
} // namespace gr } // namespace gr
#endif /* INCLUDED_IEEE802_11_OFDM_SYNC_LONG_H */ #endif /* INCLUDED_IEEE802_11_SYNC_LONG_H */
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,8 +14,8 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_OFDM_SYNC_SHORT_H #ifndef INCLUDED_IEEE802_11_SYNC_SHORT_H
#define INCLUDED_IEEE802_11_OFDM_SYNC_SHORT_H #define INCLUDED_IEEE802_11_SYNC_SHORT_H
#include <ieee802-11/api.h> #include <ieee802-11/api.h>
#include <gnuradio/block.h> #include <gnuradio/block.h>
@@ -23,11 +23,11 @@
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
class IEEE802_11_API ofdm_sync_short : virtual public block class IEEE802_11_API sync_short : virtual public block
{ {
public: public:
typedef boost::shared_ptr<ofdm_sync_short> sptr; typedef boost::shared_ptr<sync_short> sptr;
static sptr make(double threshold, unsigned int min_plateau, bool log = false, bool debug = false); static sptr make(double threshold, unsigned int min_plateau, bool log = false, bool debug = false);
}; };
@@ -35,4 +35,4 @@ public:
} // namespace ieee802_11 } // namespace ieee802_11
} // namespace gr } // namespace gr
#endif /* INCLUDED_IEEE802_11_OFDM_SYNC_SHORT_H */ #endif /* INCLUDED_IEEE802_11_SYNC_SHORT_H */
-37
View File
@@ -1,37 +0,0 @@
/*
* Copyright (C) 2014 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_IEEE802_11_WIFI_EDCA_H
#define INCLUDED_IEEE802_11_WIFI_EDCA_H
#include <ieee802-11/api.h>
#include <gnuradio/block.h>
namespace gr {
namespace ieee802_11 {
class IEEE802_11_API wifi_edca : virtual public block
{
public:
typedef boost::shared_ptr<wifi_edca> sptr;
static sptr make(std::vector<uint16_t>cw_min, std::vector<uint16_t>aifsn);
};
} // namespace ieee802_11
} // namespace gr
#endif /* INCLUDED_IEEE802_11_WIFI_EDCA_H */
+16 -14
View File
@@ -1,5 +1,5 @@
# #
# Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> # Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -94,27 +94,29 @@ add_dependencies(ieee802_11_generated_sources ieee802_11_generated_includes)
######################################################################## ########################################################################
list(APPEND gr_ieee802_11_sources list(APPEND gr_ieee802_11_sources
${generated_sources} ${generated_sources}
equalizer/linear_comb.cc
equalizer/lms.cc
chunks_to_symbols_impl.cc chunks_to_symbols_impl.cc
constellations_impl.cc
decode_mac.cc
equalizer/base.cc
equalizer/comb.cc
equalizer/ls.cc
equalizer/lms.cc
equalizer/sta.cc
ether_encap_impl.cc ether_encap_impl.cc
ofdm_decode_mac.cc frame_equalizer_impl.cc
ofdm_decode_signal.cc mac.cc
ofdm_equalize_symbols.cc mapper.cc
ofdm_mac.cc parse_mac.cc
ofdm_mapper.cc signal_field_impl.cc
ofdm_parse_mac.cc sync_long.cc
ofdm_sync_long.cc sync_short.cc
ofdm_sync_short.cc
utils.cc utils.cc
wifi_edca.cc viterbi_decoder.cc
wifi_signal_field_impl.cc
) )
list(APPEND gr_ieee802_11_libs list(APPEND gr_ieee802_11_libs
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${GNURADIO_ALL_LIBRARIES} ${GNURADIO_ALL_LIBRARIES}
${ITPP_LIBRARIES}
${LOG4CPP_LIBRARIES} ${LOG4CPP_LIBRARIES}
) )
+16 -63
View File
@@ -28,10 +28,17 @@ chunks_to_symbols::make()
return gnuradio::get_initial_sptr(new chunks_to_symbols_impl()); return gnuradio::get_initial_sptr(new chunks_to_symbols_impl());
} }
chunks_to_symbols_impl::chunks_to_symbols_impl() chunks_to_symbols_impl::chunks_to_symbols_impl() :
: tagged_stream_block("wifi_chunks_to_symbols", tagged_stream_block("chunks_to_symbols",
io_signature::make(1, 1, sizeof(char)), io_signature::make(1, 1, sizeof(char)),
io_signature::make(1, 1, sizeof(gr_complex)), "packet_len") { io_signature::make(1, 1, sizeof(gr_complex)), "packet_len") {
d_bpsk = constellation_bpsk::make();
d_qpsk = constellation_qpsk::make();
d_16qam = constellation_16qam::make();
d_64qam = constellation_64qam::make();
d_mapping = d_bpsk;
} }
chunks_to_symbols_impl::~chunks_to_symbols_impl() { } chunks_to_symbols_impl::~chunks_to_symbols_impl() { }
@@ -56,27 +63,25 @@ chunks_to_symbols_impl::work(int noutput_items,
Encoding encoding = (Encoding)pmt::to_long(tags[0].value); Encoding encoding = (Encoding)pmt::to_long(tags[0].value);
const gr_complex *mapping;
switch (encoding) { switch (encoding) {
case BPSK_1_2: case BPSK_1_2:
case BPSK_3_4: case BPSK_3_4:
mapping = BPSK; d_mapping = d_bpsk;
break; break;
case QPSK_1_2: case QPSK_1_2:
case QPSK_3_4: case QPSK_3_4:
mapping = QPSK; d_mapping = d_qpsk;
break; break;
case QAM16_1_2: case QAM16_1_2:
case QAM16_3_4: case QAM16_3_4:
mapping = QAM16; d_mapping = d_16qam;
break; break;
case QAM64_2_3: case QAM64_2_3:
case QAM64_3_4: case QAM64_3_4:
mapping = QAM64; d_mapping = d_64qam;
break; break;
default: default:
@@ -85,60 +90,8 @@ chunks_to_symbols_impl::work(int noutput_items,
} }
for(int i = 0; i < ninput_items[0]; i++) { for(int i = 0; i < ninput_items[0]; i++) {
out[i] = mapping[in[i]]; d_mapping->map_to_points(in[i], out + i);
} }
return ninput_items[0]; return ninput_items[0];
} }
const gr_complex chunks_to_symbols_impl::BPSK[2] = {
gr_complex(-1.0, 0.0), gr_complex(1.0, 0.0)};
const gr_complex chunks_to_symbols_impl::QPSK[4] = {
gr_complex(-0.7071, -0.7071), gr_complex(-0.7071, 0.7071),
gr_complex(+0.7071, -0.7071), gr_complex(+0.7071, 0.7071)};
const gr_complex chunks_to_symbols_impl::QAM16[16] = {
gr_complex(-0.9487, -0.9487), gr_complex(-0.9487, -0.3162),
gr_complex(-0.9487, 0.9487), gr_complex(-0.9487, 0.3162),
gr_complex(-0.3162, -0.9487), gr_complex(-0.3162, -0.3162),
gr_complex(-0.3162, 0.9487), gr_complex(-0.3162, 0.3162),
gr_complex(0.9487, -0.9487), gr_complex(0.9487, -0.3162),
gr_complex(0.9487, 0.9487), gr_complex(0.9487, 0.3162),
gr_complex(0.3162, -0.9487), gr_complex(0.3162, -0.3162),
gr_complex(0.3162, 0.9487), gr_complex(0.3162, 0.3162)};
const gr_complex chunks_to_symbols_impl::QAM64[64] = {
gr_complex(-1.0801, -1.0801), gr_complex(-1.0801, -0.7715),
gr_complex(-1.0801, -0.1543), gr_complex(-1.0801, -0.4629),
gr_complex(-1.0801, 1.0801), gr_complex(-1.0801, 0.7715),
gr_complex(-1.0801, 0.1543), gr_complex(-1.0801, 0.4629),
gr_complex(-0.7715, -1.0801), gr_complex(-0.7715, -0.7715),
gr_complex(-0.7715, -0.1543), gr_complex(-0.7715, -0.4629),
gr_complex(-0.7715, 1.0801), gr_complex(-0.7715, 0.7715),
gr_complex(-0.7715, 0.1543), gr_complex(-0.7715, 0.4629),
gr_complex(-0.1543, -1.0801), gr_complex(-0.1543, -0.7715),
gr_complex(-0.1543, -0.1543), gr_complex(-0.1543, -0.4629),
gr_complex(-0.1543, 1.0801), gr_complex(-0.1543, 0.7715),
gr_complex(-0.1543, 0.1543), gr_complex(-0.1543, 0.4629),
gr_complex(-0.4629, -1.0801), gr_complex(-0.4629, -0.7715),
gr_complex(-0.4629, -0.1543), gr_complex(-0.4629, -0.4629),
gr_complex(-0.4629, 1.0801), gr_complex(-0.4629, 0.7715),
gr_complex(-0.4629, 0.1543), gr_complex(-0.4629, 0.4629),
gr_complex(1.0801, -1.0801), gr_complex(1.0801, -0.7715),
gr_complex(1.0801, -0.1543), gr_complex(1.0801, -0.4629),
gr_complex(1.0801, 1.0801), gr_complex(1.0801, 0.7715),
gr_complex(1.0801, 0.1543), gr_complex(1.0801, 0.4629),
gr_complex(0.7715, -1.0801), gr_complex(0.7715, -0.7715),
gr_complex(0.7715, -0.1543), gr_complex(0.7715, -0.4629),
gr_complex(0.7715, 1.0801), gr_complex(0.7715, 0.7715),
gr_complex(0.7715, 0.1543), gr_complex(0.7715, 0.4629),
gr_complex(0.1543, -1.0801), gr_complex(0.1543, -0.7715),
gr_complex(0.1543, -0.1543), gr_complex(0.1543, -0.4629),
gr_complex(0.1543, 1.0801), gr_complex(0.1543, 0.7715),
gr_complex(0.1543, 0.1543), gr_complex(0.1543, 0.4629),
gr_complex(0.4629, -1.0801), gr_complex(0.4629, -0.7715),
gr_complex(0.4629, -0.1543), gr_complex(0.4629, -0.4629),
gr_complex(0.4629, 1.0801), gr_complex(0.4629, 0.7715),
gr_complex(0.4629, 0.1543), gr_complex(0.4629, 0.4629)};
+7 -5
View File
@@ -18,6 +18,7 @@
#define INCLUDED_IEEE802_11_CHUNKS_TO_SYMBOLS_IMPL_H #define INCLUDED_IEEE802_11_CHUNKS_TO_SYMBOLS_IMPL_H
#include <ieee802-11/chunks_to_symbols.h> #include <ieee802-11/chunks_to_symbols.h>
#include <ieee802-11/constellations.h>
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
@@ -33,11 +34,12 @@ public:
gr_vector_const_void_star &input_items, gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items); gr_vector_void_star &output_items);
protected: private:
static const gr_complex BPSK[2]; boost::shared_ptr<gr::digital::constellation> d_mapping;
static const gr_complex QPSK[4]; constellation_bpsk::sptr d_bpsk;
static const gr_complex QAM16[16]; constellation_qpsk::sptr d_qpsk;
static const gr_complex QAM64[64]; constellation_16qam::sptr d_16qam;
constellation_64qam::sptr d_64qam;
}; };
} /* namespace ieee802_11 */ } /* namespace ieee802_11 */
+235
View File
@@ -0,0 +1,235 @@
/*
* Copyright (C) 2016 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "constellations_impl.h"
using namespace gr::ieee802_11;
constellation_bpsk::sptr
constellation_bpsk::make() {
return constellation_bpsk::sptr(new constellation_bpsk_impl());
}
constellation_bpsk::constellation_bpsk() {}
constellation_bpsk_impl::constellation_bpsk_impl() {
d_constellation.resize(2);
d_constellation[0] = gr_complex(-1, 0);
d_constellation[1] = gr_complex(1, 0);
d_rotational_symmetry = 2;
d_dimensionality = 1;
calc_arity();
}
constellation_bpsk_impl::~constellation_bpsk_impl() {
}
unsigned int
constellation_bpsk_impl::decision_maker(const gr_complex *sample) {
return (real(*sample) > 0);
}
/**********************************************************/
constellation_qpsk::sptr
constellation_qpsk::make() {
return constellation_qpsk::sptr(new constellation_qpsk_impl());
}
constellation_qpsk::constellation_qpsk() {}
constellation_qpsk_impl::constellation_qpsk_impl() {
const float level = sqrt(float(0.5));
d_constellation.resize(4);
// Gray-coded
d_constellation[0] = gr_complex(-level, -level);
d_constellation[1] = gr_complex( level, -level);
d_constellation[2] = gr_complex(-level, level);
d_constellation[3] = gr_complex( level, level);
d_rotational_symmetry = 4;
d_dimensionality = 1;
calc_arity();
}
constellation_qpsk_impl::~constellation_qpsk_impl() {
}
unsigned int
constellation_qpsk_impl::decision_maker(const gr_complex *sample) {
return 2*(imag(*sample)>0) + (real(*sample)>0);
}
/**********************************************************/
constellation_16qam::sptr
constellation_16qam::make() {
return constellation_16qam::sptr(new constellation_16qam_impl());
}
constellation_16qam::constellation_16qam() {}
constellation_16qam_impl::constellation_16qam_impl()
{
const float level = sqrt(float(0.1));
d_constellation.resize(16);
d_constellation[ 0] = gr_complex(-3*level,-3*level);
d_constellation[ 1] = gr_complex( 3*level,-3*level);
d_constellation[ 2] = gr_complex(-1*level,-3*level);
d_constellation[ 3] = gr_complex( 1*level,-3*level);
d_constellation[ 4] = gr_complex(-3*level, 3*level);
d_constellation[ 5] = gr_complex( 3*level, 3*level);
d_constellation[ 6] = gr_complex(-1*level, 3*level);
d_constellation[ 7] = gr_complex( 1*level, 3*level);
d_constellation[ 8] = gr_complex(-3*level,-1*level);
d_constellation[ 9] = gr_complex( 3*level,-1*level);
d_constellation[10] = gr_complex(-1*level,-1*level);
d_constellation[11] = gr_complex( 1*level,-1*level);
d_constellation[12] = gr_complex(-3*level, 1*level);
d_constellation[13] = gr_complex( 3*level, 1*level);
d_constellation[14] = gr_complex(-1*level, 1*level);
d_constellation[15] = gr_complex( 1*level, 1*level);
d_rotational_symmetry = 4;
d_dimensionality = 1;
calc_arity();
}
constellation_16qam_impl::~constellation_16qam_impl() {
}
unsigned int
constellation_16qam_impl::decision_maker(const gr_complex *sample)
{
unsigned int ret = 0;
const float level = sqrt(float(0.1));
float re = sample->real();
float im = sample->imag();
ret |= re > 0;
ret |= (std::abs(re) < (2*level)) << 1;
ret |= (im > 0) << 2;
ret |= (std::abs(im) < (2*level)) << 3;
return ret;
}
/**********************************************************/
constellation_64qam::sptr
constellation_64qam::make() {
return constellation_64qam::sptr(new constellation_64qam_impl());
}
constellation_64qam::constellation_64qam() {}
constellation_64qam_impl::constellation_64qam_impl() {
const float level = sqrt(float(1/42.0));
d_constellation.resize(64);
d_constellation[ 0] = gr_complex(-7*level,-7*level);
d_constellation[ 1] = gr_complex( 7*level,-7*level);
d_constellation[ 2] = gr_complex(-1*level,-7*level);
d_constellation[ 3] = gr_complex( 1*level,-7*level);
d_constellation[ 4] = gr_complex(-5*level,-7*level);
d_constellation[ 5] = gr_complex( 5*level,-7*level);
d_constellation[ 6] = gr_complex(-3*level,-7*level);
d_constellation[ 7] = gr_complex( 3*level,-7*level);
d_constellation[ 8] = gr_complex(-7*level, 7*level);
d_constellation[ 9] = gr_complex( 7*level, 7*level);
d_constellation[10] = gr_complex(-1*level, 7*level);
d_constellation[11] = gr_complex( 1*level, 7*level);
d_constellation[12] = gr_complex(-5*level, 7*level);
d_constellation[13] = gr_complex( 5*level, 7*level);
d_constellation[14] = gr_complex(-3*level, 7*level);
d_constellation[15] = gr_complex( 3*level, 7*level);
d_constellation[16] = gr_complex(-7*level,-1*level);
d_constellation[17] = gr_complex( 7*level,-1*level);
d_constellation[18] = gr_complex(-1*level,-1*level);
d_constellation[19] = gr_complex( 1*level,-1*level);
d_constellation[20] = gr_complex(-5*level,-1*level);
d_constellation[21] = gr_complex( 5*level,-1*level);
d_constellation[22] = gr_complex(-3*level,-1*level);
d_constellation[23] = gr_complex( 3*level,-1*level);
d_constellation[24] = gr_complex(-7*level, 1*level);
d_constellation[25] = gr_complex( 7*level, 1*level);
d_constellation[26] = gr_complex(-1*level, 1*level);
d_constellation[27] = gr_complex( 1*level, 1*level);
d_constellation[28] = gr_complex(-5*level, 1*level);
d_constellation[29] = gr_complex( 5*level, 1*level);
d_constellation[30] = gr_complex(-3*level, 1*level);
d_constellation[31] = gr_complex( 3*level, 1*level);
d_constellation[32] = gr_complex(-7*level,-5*level);
d_constellation[33] = gr_complex( 7*level,-5*level);
d_constellation[34] = gr_complex(-1*level,-5*level);
d_constellation[35] = gr_complex( 1*level,-5*level);
d_constellation[36] = gr_complex(-5*level,-5*level);
d_constellation[37] = gr_complex( 5*level,-5*level);
d_constellation[38] = gr_complex(-3*level,-5*level);
d_constellation[39] = gr_complex( 3*level,-5*level);
d_constellation[40] = gr_complex(-7*level, 5*level);
d_constellation[41] = gr_complex( 7*level, 5*level);
d_constellation[42] = gr_complex(-1*level, 5*level);
d_constellation[43] = gr_complex( 1*level, 5*level);
d_constellation[44] = gr_complex(-5*level, 5*level);
d_constellation[45] = gr_complex( 5*level, 5*level);
d_constellation[46] = gr_complex(-3*level, 5*level);
d_constellation[47] = gr_complex( 3*level, 5*level);
d_constellation[48] = gr_complex(-7*level,-3*level);
d_constellation[49] = gr_complex( 7*level,-3*level);
d_constellation[50] = gr_complex(-1*level,-3*level);
d_constellation[51] = gr_complex( 1*level,-3*level);
d_constellation[52] = gr_complex(-5*level,-3*level);
d_constellation[53] = gr_complex( 5*level,-3*level);
d_constellation[54] = gr_complex(-3*level,-3*level);
d_constellation[55] = gr_complex( 3*level,-3*level);
d_constellation[56] = gr_complex(-7*level, 3*level);
d_constellation[57] = gr_complex( 7*level, 3*level);
d_constellation[58] = gr_complex(-1*level, 3*level);
d_constellation[59] = gr_complex( 1*level, 3*level);
d_constellation[60] = gr_complex(-5*level, 3*level);
d_constellation[61] = gr_complex( 5*level, 3*level);
d_constellation[62] = gr_complex(-3*level, 3*level);
d_constellation[63] = gr_complex( 3*level, 3*level);
d_rotational_symmetry = 4;
d_dimensionality = 1;
calc_arity();
}
constellation_64qam_impl::~constellation_64qam_impl() {
}
unsigned int
constellation_64qam_impl::decision_maker(const gr_complex *sample) {
unsigned int ret = 0;
const float level = sqrt(float(1/42.0));
float re = sample->real();
float im = sample->imag();
ret |= re > 0;
ret |= (std::abs(re) < (4*level)) << 1;
ret |= (std::abs(re) < (6*level) && std::abs(re) > (2*level)) << 2;
ret |= (im > 0) << 3;
ret |= (std::abs(im) < (4*level)) << 4;
ret |= (std::abs(im) < (6*level) && std::abs(im) > (2*level)) << 5;
return ret;
}
+71
View File
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2016 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_IEEE802_11_CONSTELLATIONS_IMPL_H
#define INCLUDED_IEEE802_11_CONSTELLATIONS_IMPL_H
#include <ieee802-11/constellations.h>
namespace gr {
namespace ieee802_11 {
class constellation_bpsk_impl : public constellation_bpsk
{
public:
constellation_bpsk_impl();
~constellation_bpsk_impl();
unsigned int decision_maker(const gr_complex *sample);
};
class constellation_qpsk_impl : public constellation_qpsk
{
public:
constellation_qpsk_impl();
~constellation_qpsk_impl();
unsigned int decision_maker(const gr_complex *sample);
};
class constellation_16qam_impl : public constellation_16qam
{
public:
constellation_16qam_impl();
~constellation_16qam_impl();
unsigned int decision_maker(const gr_complex *sample);
};
class constellation_64qam_impl : public constellation_64qam
{
public:
constellation_64qam_impl();
~constellation_64qam_impl();
unsigned int decision_maker(const gr_complex *sample);
};
} // namespace ieee802_11
} // namespace gr
#endif /* INCLUDED_IEEE802_11_CONSTELLATIONS_IMPL_H */
+247
View File
@@ -0,0 +1,247 @@
/*
* Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ieee802-11/decode_mac.h>
#include "utils.h"
#include "viterbi_decoder.h"
#include <boost/crc.hpp>
#include <gnuradio/io_signature.h>
using namespace gr::ieee802_11;
#define LINKTYPE_IEEE802_11 105 /* http://www.tcpdump.org/linktypes.html */
class decode_mac_impl : public decode_mac {
public:
decode_mac_impl(bool log, bool debug) :
block("decode_mac",
gr::io_signature::make(1, 1, 48),
gr::io_signature::make(0, 0, 0)),
d_log(log),
d_debug(debug),
d_snr(0),
d_nom_freq(0.0),
d_freq_offset(0.0),
d_ofdm(BPSK_1_2),
d_frame(d_ofdm, 0),
d_frame_complete(true) {
message_port_register_out(pmt::mp("out"));
}
int general_work (int noutput_items, gr_vector_int& ninput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items) {
const uint8_t *in = (const uint8_t*)input_items[0];
int i = 0;
std::vector<gr::tag_t> tags;
const uint64_t nread = this->nitems_read(0);
dout << "Decode MAC: input " << ninput_items[0] << std::endl;
while(i < ninput_items[0]) {
get_tags_in_range(tags, 0, nread + i, nread + i + 1,
pmt::string_to_symbol("wifi_start"));
if(tags.size()) {
if (d_frame_complete == false) {
dout << "Warning: starting to receive new frame before old frame was complete" << std::endl;
dout << "Already copied " << copied << " out of " << d_frame.n_sym << " symbols of last frame" << std::endl;
}
d_frame_complete = false;
pmt::pmt_t dict = tags[0].value;
int len_data = pmt::to_uint64(pmt::dict_ref(dict, pmt::mp("frame_bytes"), pmt::from_uint64(MAX_PSDU_SIZE+1)));
int encoding = pmt::to_uint64(pmt::dict_ref(dict, pmt::mp("encoding"), pmt::from_uint64(0)));
d_snr = pmt::to_double(pmt::dict_ref(dict, pmt::mp("snr"), pmt::from_double(0)));
d_nom_freq = pmt::to_double(pmt::dict_ref(dict, pmt::mp("freq"), pmt::from_double(0)));
d_freq_offset = pmt::to_double(pmt::dict_ref(dict, pmt::mp("freq_offset"), pmt::from_double(0)));
ofdm_param ofdm = ofdm_param((Encoding)encoding);
frame_param frame = frame_param(ofdm, len_data);
// check for maximum frame size
if(frame.n_sym <= MAX_SYM && frame.psdu_size <= MAX_PSDU_SIZE) {
d_ofdm = ofdm;
d_frame = frame;
copied = 0;
dout << "Decode MAC: frame start -- len " << len_data
<< " symbols " << frame.n_sym << " encoding "
<< encoding << std::endl;
} else {
dout << "Dropping frame which is too large (symbols or bits)" << std::endl;
}
}
if(copied < d_frame.n_sym) {
dout << "copy one symbol, copied " << copied << " out of " << d_frame.n_sym << std::endl;
std::memcpy(d_rx_symbols + (copied * 48), in, 48);
copied++;
if(copied == d_frame.n_sym) {
dout << "received complete frame - decoding" << std::endl;
decode();
in += 48;
i++;
d_frame_complete = true;
break;
}
}
in += 48;
i++;
}
consume(0, i);
return 0;
}
void decode() {
for(int i = 0; i < d_frame.n_sym * 48; i++) {
for(int k = 0; k < d_ofdm.n_bpsc; k++) {
d_rx_bits[i*d_ofdm.n_bpsc + k] = !!(d_rx_symbols[i] & (1 << k));
}
}
deinterleave();
uint8_t *decoded = d_decoder.decode(&d_ofdm, &d_frame, d_deinterleaved_bits);
descramble(decoded);
print_output();
// skip service field
boost::crc_32_type result;
result.process_bytes(out_bytes + 2, d_frame.psdu_size);
if(result.checksum() != 558161692) {
dout << "checksum wrong -- dropping" << std::endl;
return;
}
mylog(boost::format("encoding: %1% - length: %2% - symbols: %3%")
% d_ofdm.encoding % d_frame.psdu_size % d_frame.n_sym);
// create PDU
pmt::pmt_t blob = pmt::make_blob(out_bytes + 2, d_frame.psdu_size - 4);
pmt::pmt_t enc = pmt::from_uint64(d_ofdm.encoding);
pmt::pmt_t dict = pmt::make_dict();
dict = pmt::dict_add(dict, pmt::mp("encoding"), enc);
dict = pmt::dict_add(dict, pmt::mp("snr"), pmt::from_double(d_snr));
dict = pmt::dict_add(dict, pmt::mp("nomfreq"), pmt::from_double(d_nom_freq));
dict = pmt::dict_add(dict, pmt::mp("freqofs"), pmt::from_double(d_freq_offset));
dict = pmt::dict_add(dict, pmt::mp("dlt"), pmt::from_long(LINKTYPE_IEEE802_11));
message_port_pub(pmt::mp("out"), pmt::cons(dict, blob));
}
void deinterleave() {
int n_cbps = d_ofdm.n_cbps;
int first[n_cbps];
int second[n_cbps];
int s = std::max(d_ofdm.n_bpsc / 2, 1);
for(int j = 0; j < n_cbps; j++) {
first[j] = s * (j / s) + ((j + int(floor(16.0 * j / n_cbps))) % s);
}
for(int i = 0; i < n_cbps; i++) {
second[i] = 16 * i - (n_cbps - 1) * int(floor(16.0 * i / n_cbps));
}
int count = 0;
for(int i = 0; i < d_frame.n_sym; i++) {
for(int k = 0; k < n_cbps; k++) {
d_deinterleaved_bits[i * n_cbps + second[first[k]]] = d_rx_bits[i * n_cbps + k];
}
}
}
void descramble (uint8_t *decoded_bits) {
int state = 0;
std::memset(out_bytes, 0, d_frame.psdu_size+2);
for(int i = 0; i < 7; i++) {
if(decoded_bits[i]) {
state |= 1 << (6 - i);
}
}
out_bytes[0] = state;
int feedback;
int bit;
for(int i = 7; i < d_frame.psdu_size*8+16; i++) {
feedback = ((!!(state & 64))) ^ (!!(state & 8));
bit = feedback ^ (decoded_bits[i] & 0x1);
out_bytes[i/8] |= bit << (i%8);
state = ((state << 1) & 0x7e) | feedback;
}
}
void print_output() {
dout << std::endl;
dout << "psdu size" << d_frame.psdu_size << std::endl;
for(int i = 2; i < d_frame.psdu_size+2; i++) {
dout << std::setfill('0') << std::setw(2) << std::hex << ((unsigned int)out_bytes[i] & 0xFF) << std::dec << " ";
if(i % 16 == 15) {
dout << std::endl;
}
}
dout << std::endl;
for(int i = 2; i < d_frame.psdu_size+2; i++) {
if((out_bytes[i] > 31) && (out_bytes[i] < 127)) {
dout << ((char) out_bytes[i]);
} else {
dout << ".";
}
}
dout << std::endl;
}
private:
bool d_debug;
bool d_log;
frame_param d_frame;
ofdm_param d_ofdm;
double d_snr; // dB
double d_nom_freq; // nominal frequency, Hz
double d_freq_offset; // frequency offset, Hz
viterbi_decoder d_decoder;
uint8_t d_rx_symbols[48 * MAX_SYM];
uint8_t d_rx_bits[MAX_ENCODED_BITS];
uint8_t d_deinterleaved_bits[MAX_ENCODED_BITS];
uint8_t out_bytes[MAX_PSDU_SIZE + 2]; // 2 for signal field
int copied;
bool d_frame_complete;
};
decode_mac::sptr
decode_mac::make(bool log, bool debug) {
return gnuradio::get_initial_sptr(new decode_mac_impl(log, debug));
}
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2016 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base.h"
#include <cstring>
#include <iostream>
using namespace gr::ieee802_11::equalizer;
const gr_complex base::LONG[] = {
0, 0, 0, 0, 0, 0, 1, 1, -1, -1,
1, 1, -1, 1, -1, 1, 1, 1, 1, 1,
1, -1, -1, 1, 1, -1, 1, -1, 1, 1,
1, 1, 0, 1, -1, -1, 1, 1, -1, 1,
-1, 1, -1, -1, -1, -1, -1, 1, 1, -1,
-1, 1, -1, 1, -1, 1, 1, 1, 1, 0,
0, 0, 0, 0
};
const gr_complex base::POLARITY[127] = {
1, 1, 1, 1,-1,-1,-1, 1,-1,-1,-1,-1, 1, 1,-1, 1,
-1,-1, 1, 1,-1, 1, 1,-1, 1, 1, 1, 1, 1, 1,-1, 1,
1, 1,-1, 1, 1,-1,-1, 1, 1, 1,-1, 1,-1,-1,-1, 1,
-1, 1,-1,-1, 1,-1,-1, 1, 1, 1, 1, 1,-1,-1, 1, 1,
-1,-1, 1,-1, 1,-1, 1, 1,-1,-1,-1, 1, 1,-1,-1,-1,
-1, 1,-1,-1, 1,-1, 1, 1, 1, 1,-1, 1,-1, 1,-1, 1,
-1,-1,-1,-1,-1, 1,-1, 1, 1,-1, 1,-1, 1, 1, 1,-1,
-1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1,-1,-1,-1,-1 };
+8 -1
View File
@@ -19,6 +19,7 @@
#define INCLUDED_IEEE802_11_EQUALIZER_BASE_H #define INCLUDED_IEEE802_11_EQUALIZER_BASE_H
#include <gnuradio/gr_complex.h> #include <gnuradio/gr_complex.h>
#include <gnuradio/digital/constellation.h>
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
@@ -27,7 +28,13 @@ namespace equalizer {
class base { class base {
public: public:
virtual ~base() {}; virtual ~base() {};
virtual void equalize(const gr_complex *in, gr_complex *out, int n) = 0; virtual void equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod) = 0;
virtual double get_snr() = 0;
static const gr_complex POLARITY[127];
protected:
static const gr_complex LONG[64];
}; };
} /* namespace channel_estimation */ } /* namespace channel_estimation */
+77
View File
@@ -0,0 +1,77 @@
/*
* Copyright (C) 2015 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "comb.h"
using namespace gr::ieee802_11::equalizer;
void comb::equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod) {
gr_complex pilot[4];
if(n < 2) {
pilot[0] = in[11];
pilot[1] = -in[25];
pilot[2] = in[39];
pilot[3] = in[53];
} else {
gr_complex p = POLARITY[(n - 2) % 127];
pilot[0] = in[11] * p;
pilot[1] = in[25] * p;
pilot[2] = in[39] * p;
pilot[3] = in[53] * -p;
}
gr_complex avg = (pilot[0] + pilot[1] + pilot[2] + pilot[3]) / gr_complex(4, 0);
for(int i = 0; i < 64; i++) {
gr_complex H;
if(i <= 11) {
H = gr_complex((11-i) / 11.0, 0) * avg + gr_complex( i / 11.0, 0) * pilot[0];
} else if(i <= 25) {
H = gr_complex((25-i) / 14.0, 0) * pilot[0] + gr_complex((i-11) / 14.0, 0) * pilot[1];
} else if(i <= 39) {
H = gr_complex((39-i) / 14.0, 0) * pilot[1] + gr_complex((i-25) / 14.0, 0) * pilot[2];
} else if(i <= 53) {
H = gr_complex((53-i) / 14.0, 0) * pilot[2] + gr_complex((i-39) / 14.0, 0) * pilot[3];
} else {
H = gr_complex((64-i) / 11.0, 0) * pilot[3] + gr_complex((i-53) / 11.0, 0) * avg;
}
if(n == 0) {
d_H[i] = H;
} else {
d_H[i] = gr_complex(1-alpha, 0) * d_H[i] + gr_complex(alpha, 0) * H;
}
}
int c = 0;
for(int i = 0; i < 64; i++) {
if( (i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) || (i < 6) || ( i > 58)) {
continue;
} else {
symbols[c] = in[i] / d_H[i];
bits[c] = mod->decision_maker(&symbols[c]);
c++;
}
}
}
double
comb::get_snr() {
return 42;
}
@@ -15,8 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_EQUALIZER_LINEAR_COMB_H #ifndef INCLUDED_IEEE802_11_EQUALIZER_COMB_H
#define INCLUDED_IEEE802_11_EQUALIZER_LINEAR_COMB_H #define INCLUDED_IEEE802_11_EQUALIZER_COMB_H
#include "base.h" #include "base.h"
@@ -24,16 +24,21 @@ namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
namespace equalizer { namespace equalizer {
class linear_comb: public base { class comb: public base {
public: public:
virtual void equalize(const gr_complex *in, gr_complex *out, int n); virtual void equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod);
double get_snr();
private: private:
static const gr_complex POLARITY[127]; gr_complex d_H[64];
const double alpha = 0.2;
}; };
} /* namespace channel_estimation */ } /* namespace channel_estimation */
} /* namespace ieee802_11 */ } /* namespace ieee802_11 */
} /* namespace gr */ } /* namespace gr */
#endif /* INCLUDED_IEEE802_11_EQUALIZER_LINEAR_COMB_H */ #endif /* INCLUDED_IEEE802_11_EQUALIZER_COMB_H */
-63
View File
@@ -1,63 +0,0 @@
/*
* Copyright (C) 2015 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "linear_comb.h"
using namespace gr::ieee802_11::equalizer;
void linear_comb::equalize(const gr_complex *in, gr_complex *out, int n) {
if(n < 2)
return;
double avg_mag = (abs(in[11]) + abs(in[25]) + abs(in[39]) + abs(in[53])) / 4;
gr_complex p = POLARITY[(n - 2) % 127 ];
double p1 = arg( p * in[11]);
double p2 = arg( p * in[25] * conj(p * in[11])) + p1;
double p3 = arg( p * in[39] * conj(p * in[25])) + p2;
double p4 = arg(-p * in[53] * conj(p * in[39])) + p3;
double my = (p1 + p2 + p3 + p4) / 4;
double mx = (11.0 + 25 + 39 + 53) / 4;
double var = (((11.0 * 11.0) + (25.0 * 25.0) + (39.0 * 39.0) + (53.0 * 53.0)) / 4) - (mx * mx);
double cov = (( (p1 * 11) + (p2 * 25) + (p3 * 39) + (p4 * 53) ) / 4) - (mx * my);
double beta = cov / var;
double alpha = my - beta * mx;
int c = 0;
for(int n = 0; n < 64; n++) {
if( (n == 11) || (n == 25) || (n == 32) || (n == 39) || (n == 53) || (n < 6) || ( n > 58)) {
continue;
} else {
out[c] = in[n] * exp(gr_complex(0, -n * beta - alpha)) * gr_complex(1 / avg_mag, 0);
c++;
}
}
}
const gr_complex linear_comb::POLARITY[127] = {
1, 1, 1, 1,-1,-1,-1, 1,-1,-1,-1,-1, 1, 1,-1, 1,
-1,-1, 1, 1,-1, 1, 1,-1, 1, 1, 1, 1, 1, 1,-1, 1,
1, 1,-1, 1, 1,-1,-1, 1, 1, 1,-1, 1,-1,-1,-1, 1,
-1, 1,-1,-1, 1,-1,-1, 1, 1, 1, 1, 1,-1,-1, 1, 1,
-1,-1, 1,-1, 1,-1, 1, 1,-1,-1,-1, 1, 1,-1,-1,-1,
-1, 1,-1,-1, 1,-1, 1, 1, 1, 1,-1, 1,-1, 1,-1, 1,
-1,-1,-1,-1,-1, 1,-1, 1, 1,-1, 1,-1, 1, 1, 1,-1,
-1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1,-1,-1,-1,-1 };
+24 -64
View File
@@ -21,84 +21,44 @@
using namespace gr::ieee802_11::equalizer; using namespace gr::ieee802_11::equalizer;
void lms::equalize(const gr_complex *in, gr_complex *out, int n) { void lms::equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod) {
static float freq_offset = 0;
static float freq_sum = 0;
static float alpha = 0.9;
if(n == 0) { if(n == 0) {
std::memcpy(carrier, in, 64 * sizeof(gr_complex)); std::memcpy(d_H, in, 64 * sizeof(gr_complex));
} else if(n == 1) { } else if(n == 1) {
gr_complex sum = double signal = 0;
(carrier[11] * conj(in[11])) + double noise = 0;
(carrier[25] * conj(in[25])) +
(carrier[39] * conj(in[39])) +
(carrier[53] * conj(in[53]));
freq_offset = arg(sum);
freq_sum = 0;
for(int i = 0; i < 64; i++) { for(int i = 0; i < 64; i++) {
carrier[i] += in[i]; if((i == 32) || (i < 6) || ( i > 58)) {
carrier[i] *= ref[i] * gr_complex(0.5, 0); continue;
}
noise += std::pow(std::abs(d_H[i] - in[i]), 2);
signal += std::pow(std::abs(d_H[i] + in[i]), 2);
d_H[i] += in[i];
d_H[i] /= LONG[i] * gr_complex(2, 0);
} }
d_snr = 10 * std::log10(signal / noise / 2);
} else { } else {
gr_complex p = POLARITY[(n - 2) % 127];
gr_complex sum =
(carrier[11] * conj(in[11]) * p) +
(carrier[25] * conj(in[25]) * p) +
(carrier[39] * conj(in[39]) * p) +
(carrier[53] * conj(in[53]) * -p);
freq_offset = (1 - alpha) * freq_offset + alpha * arg(sum);
freq_sum += freq_offset;
//std::cout << "lms: symbol " << n
// << " p1 " << abs(carrier[11] * conj(in[11]) * p)
// << " p2 " << abs(carrier[25] * conj(in[25]) * p)
// << " p3 " << abs(carrier[39] * conj(in[39]) * p)
// << " p4 " << abs(carrier[53] * conj(in[53]) * -p)
// << std::endl;
//std::cout << "lms: symbol " << n
// << " p1 " << arg(carrier[11] * conj(in[11]) * p)
// << " p2 " << arg(carrier[25] * conj(in[25]) * p)
// << " p3 " << arg(carrier[39] * conj(in[39]) * p)
// << " p4 " << arg(carrier[53] * conj(in[53]) * -p)
// << std::endl;
carrier[11] = in[11] * p;
carrier[25] = in[25] * p;
carrier[39] = in[39] * p;
carrier[53] = in[53] * -p;
int c = 0; int c = 0;
for(int i = 0; i < 64; i++) { for(int i = 0; i < 64; i++) {
if( (i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) || (i < 6) || ( i > 58)) { if( (i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) || (i < 6) || ( i > 58)) {
continue; continue;
} else { } else {
out[c] = in[i] / carrier[i] * exp(gr_complex(0, freq_sum)); symbols[c] = in[i] / d_H[i];
bits[c] = mod->decision_maker(&symbols[c]);
gr_complex point;
mod->map_to_points(bits[c], &point);
d_H[i] = gr_complex(1-alpha,0) * d_H[i] + gr_complex(alpha,0) * in[i] / point;
c++; c++;
} }
} }
} }
} }
const gr_complex lms::ref[] = { double
0, 0, 0, 0, 0, 0, 1, 1, -1, -1, lms::get_snr() {
1, 1, -1, 1, -1, 1, 1, 1, 1, 1, return d_snr;
1, -1, -1, 1, 1, -1, 1, -1, 1, 1, }
1, 1, 0, 1, -1, -1, 1, 1, -1, 1,
-1, 1, -1, -1, -1, -1, -1, 1, 1, -1,
-1, 1, -1, 1, -1, 1, 1, 1, 1, 0,
0, 0, 0, 0
};
const gr_complex lms::POLARITY[127] = {
1, 1, 1, 1,-1,-1,-1, 1,-1,-1,-1,-1, 1, 1,-1, 1,
-1,-1, 1, 1,-1, 1, 1,-1, 1, 1, 1, 1, 1, 1,-1, 1,
1, 1,-1, 1, 1,-1,-1, 1, 1, 1,-1, 1,-1,-1,-1, 1,
-1, 1,-1,-1, 1,-1,-1, 1, 1, 1, 1, 1,-1,-1, 1, 1,
-1,-1, 1,-1, 1,-1, 1, 1,-1,-1,-1, 1, 1,-1,-1,-1,
-1, 1,-1,-1, 1,-1, 1, 1, 1, 1,-1, 1,-1, 1,-1, 1,
-1,-1,-1,-1,-1, 1,-1, 1, 1,-1, 1,-1, 1, 1, 1,-1,
-1, 1,-1,-1,-1, 1, 1, 1,-1,-1,-1,-1,-1,-1,-1 };
+7 -5
View File
@@ -27,11 +27,14 @@ namespace equalizer {
class lms: public base { class lms: public base {
public: public:
virtual void equalize(const gr_complex *in, gr_complex *out, int n); virtual void equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod);
private: private:
gr_complex carrier[64]; double get_snr();
static const gr_complex ref[64];
static const gr_complex POLARITY[127];
gr_complex d_H[64];
double d_snr;
const double alpha = 0.5;
}; };
} /* namespace channel_estimation */ } /* namespace channel_estimation */
@@ -39,4 +42,3 @@ private:
} /* namespace gr */ } /* namespace gr */
#endif /* INCLUDED_IEEE802_11_EQUALIZER_LMS_H */ #endif /* INCLUDED_IEEE802_11_EQUALIZER_LMS_H */
+61
View File
@@ -0,0 +1,61 @@
/*
* Copyright (C) 2016 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ls.h"
#include <cstring>
#include <iostream>
using namespace gr::ieee802_11::equalizer;
void ls::equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod) {
if(n == 0) {
std::memcpy(d_H, in, 64 * sizeof(gr_complex));
} else if(n == 1) {
double signal = 0;
double noise = 0;
for(int i = 0; i < 64; i++) {
if((i == 32) || (i < 6) || ( i > 58)) {
continue;
}
noise += std::pow(std::abs(d_H[i] - in[i]), 2);
signal += std::pow(std::abs(d_H[i] + in[i]), 2);
d_H[i] += in[i];
d_H[i] /= LONG[i] * gr_complex(2, 0);
}
d_snr = 10 * std::log10(signal / noise / 2);
} else {
int c = 0;
for(int i = 0; i < 64; i++) {
if( (i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) || (i < 6) || ( i > 58)) {
continue;
} else {
symbols[c] = in[i] / d_H[i];
bits[c] = mod->decision_maker(&symbols[c]);
c++;
}
}
}
}
double ls::get_snr() {
return d_snr;
}
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,26 +14,29 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_OFDM_DECODE_SIGNAL_H
#define INCLUDED_IEEE802_11_OFDM_DECODE_SIGNAL_H
#include <ieee802-11/api.h> #ifndef INCLUDED_IEEE802_11_EQUALIZER_LS_H
#include <gnuradio/block.h> #define INCLUDED_IEEE802_11_EQUALIZER_LS_H
#include "base.h"
#include <vector>
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
namespace equalizer {
class IEEE802_11_API ofdm_decode_signal : virtual public block class ls: public base {
{
public: public:
virtual void equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod);
typedef boost::shared_ptr<ofdm_decode_signal> sptr; virtual double get_snr();
static sptr make(bool log = false, bool debug = false); private:
gr_complex d_H[64];
double d_snr;
}; };
} // namespace ieee802_11 } /* namespace channel_estimation */
} // namespace gr } /* namespace ieee802_11 */
} /* namespace gr */
#endif /* INCLUDED_IEEE802_11_OFDM_DECODE_SIGNAL_H */ #endif /* INCLUDED_IEEE802_11_EQUALIZER_LS_H */
+95
View File
@@ -0,0 +1,95 @@
/*
* Copyright (C) 2015 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sta.h"
#include <cstring>
#include <iostream>
using namespace gr::ieee802_11::equalizer;
void sta::equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod) {
if(n == 0) {
std::memcpy(d_H, in, 64 * sizeof(gr_complex));
} else if(n == 1) {
double signal = 0;
double noise = 0;
for(int i = 0; i < 64; i++) {
if((i == 32) || (i < 6) || ( i > 58)) {
continue;
}
noise += std::pow(std::abs(d_H[i] - in[i]), 2);
signal += std::pow(std::abs(d_H[i] + in[i]), 2);
d_H[i] += in[i];
d_H[i] /= LONG[i] * gr_complex(2, 0);
}
d_snr = 10 * std::log10(signal / noise / 2);
} else {
gr_complex H_update[64];
gr_complex H[64];
gr_complex p = POLARITY[(n - 2) % 127];
H[11] = in[11] * p;
H[25] = in[25] * p;
H[39] = in[39] * p;
H[53] = in[53] * -p;
int c = 0;
for(int i = 0; i < 64; i++) {
if( (i == 11) || (i == 25) || (i == 32) || (i == 39) || (i == 53) || (i < 6) || ( i > 58)) {
continue;
} else {
symbols[c] = in[i] / d_H[i];
bits[c] = mod->decision_maker(&symbols[c]);
gr_complex point;
mod->map_to_points(bits[c], &point);
H[i] = in[i] / point;
c++;
}
}
for(int i = 0; i < 64; i++) {
int n = 0;
gr_complex s = 0;
for(int k = i-beta; k <= i+beta; k++) {
if((k == 32) || (k < 6) || ( k > 58)) {
continue;
}
n++;
s += H[k];
}
H_update[i] = s / gr_complex(n, 0);
}
for(int i = 0; i < 64; i++) {
if((i < 6) || ( i > 58)) {
continue;
}
d_H[i] = gr_complex(1-alpha,0) * d_H[i] + gr_complex(alpha,0) * H_update[i];
}
}
}
double
sta::get_snr() {
return d_snr;
}
+45
View File
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2015 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_IEEE802_11_EQUALIZER_STA_H
#define INCLUDED_IEEE802_11_EQUALIZER_STA_H
#include "base.h"
#include <vector>
namespace gr {
namespace ieee802_11 {
namespace equalizer {
class sta: public base {
public:
virtual void equalize(gr_complex *in, int n, gr_complex *symbols, uint8_t *bits, boost::shared_ptr<gr::digital::constellation> mod);
double get_snr();
private:
gr_complex d_H[64];
double d_snr;
const double alpha = 0.5;
const int beta = 2;
};
} /* namespace channel_estimation */
} /* namespace ieee802_11 */
} /* namespace gr */
#endif /* INCLUDED_IEEE802_11_EQUALIZER_STA_H */
+352
View File
@@ -0,0 +1,352 @@
/*
* Copyright (C) 2016 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "frame_equalizer_impl.h"
#include "equalizer/base.h"
#include "equalizer/comb.h"
#include "equalizer/lms.h"
#include "equalizer/ls.h"
#include "equalizer/sta.h"
#include "utils.h"
#include <gnuradio/io_signature.h>
namespace gr {
namespace ieee802_11 {
frame_equalizer::sptr
frame_equalizer::make(Equalizer algo, double freq, double bw, bool log, bool debug) {
return gnuradio::get_initial_sptr
(new frame_equalizer_impl(algo, freq, bw, log, debug));
}
frame_equalizer_impl::frame_equalizer_impl(Equalizer algo, double freq, double bw, bool log, bool debug) :
gr::block("frame_equalizer",
gr::io_signature::make(1, 1, 64 * sizeof(gr_complex)),
gr::io_signature::make(1, 1, 48)),
d_current_symbol(0), d_log(log), d_debug(debug), d_equalizer(NULL),
d_freq(freq), d_bw(bw), d_frame_bytes(0), d_frame_symbols(0),
d_freq_offset_from_synclong(0.0) {
message_port_register_out(pmt::mp("symbols"));
d_bpsk = constellation_bpsk::make();
d_qpsk = constellation_qpsk::make();
d_16qam = constellation_16qam::make();
d_64qam = constellation_64qam::make();
d_frame_mod = d_bpsk;
set_tag_propagation_policy(block::TPP_DONT);
set_algorithm(algo);
}
frame_equalizer_impl::~frame_equalizer_impl() {
}
void
frame_equalizer_impl::set_algorithm(Equalizer algo) {
gr::thread::scoped_lock lock(d_mutex);
delete d_equalizer;
switch(algo) {
case COMB:
dout << "Comb" << std::endl;
d_equalizer = new equalizer::comb();
break;
case LS:
dout << "LS" << std::endl;
d_equalizer = new equalizer::ls();
break;
case LMS:
dout << "LMS" << std::endl;
d_equalizer = new equalizer::lms();
break;
case STA:
dout << "STA" << std::endl;
d_equalizer = new equalizer::sta();
break;
default:
throw std::runtime_error("Algorithm not implemented");
}
}
void
frame_equalizer_impl::set_bandwidth(double bw) {
gr::thread::scoped_lock lock(d_mutex);
d_bw = bw;
}
void
frame_equalizer_impl::set_frequency(double freq) {
gr::thread::scoped_lock lock(d_mutex);
d_freq = freq;
}
void
frame_equalizer_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required) {
ninput_items_required[0] = noutput_items;
}
int
frame_equalizer_impl::general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items) {
gr::thread::scoped_lock lock(d_mutex);
const gr_complex *in = (const gr_complex *) input_items[0];
uint8_t *out = (uint8_t *) output_items[0];
int i = 0;
int o = 0;
gr_complex symbols[48];
gr_complex current_symbol[64];
dout << "FRAME EQUALIZER: input " << ninput_items[0] << " output " << noutput_items << std::endl;
while((i < ninput_items[0]) && (o < noutput_items)) {
get_tags_in_window(tags, 0, i, i + 1, pmt::string_to_symbol("wifi_start"));
// new frame
if(tags.size()) {
d_current_symbol = 0;
d_frame_symbols = 0;
d_frame_mod = d_bpsk;
d_freq_offset_from_synclong = pmt::to_double(tags.front().value) * d_bw / (2 * M_PI);
d_epsilon0 = pmt::to_double(tags.front().value) * d_bw / (2 * M_PI * d_freq);
d_er = 0;
dout << "epsilon: " << d_epsilon0 << std::endl;
}
// not interesting -> skip
if(d_current_symbol > (d_frame_symbols + 2)) {
i++;
continue;
}
std::memcpy(current_symbol, in + i*64, 64*sizeof(gr_complex));
// compensate sampling offset
for(int i = 0; i < 64; i++) {
current_symbol[i] *= exp(gr_complex(0, 2*M_PI*d_current_symbol*80*(d_epsilon0 + d_er)*(i-32)/64));
}
gr_complex p = equalizer::base::POLARITY[(d_current_symbol - 2) % 127];
double beta;
if(d_current_symbol < 2) {
beta = arg(
current_symbol[11] -
current_symbol[25] +
current_symbol[39] +
current_symbol[53]);
} else {
beta = arg(
(current_symbol[11] * p) +
(current_symbol[39] * p) +
(current_symbol[25] * p) +
(current_symbol[53] * -p));
}
double er = arg(
(conj(d_prev_pilots[0]) * current_symbol[11] * p) +
(conj(d_prev_pilots[1]) * current_symbol[25] * p) +
(conj(d_prev_pilots[2]) * current_symbol[39] * p) +
(conj(d_prev_pilots[3]) * current_symbol[53] * -p));
er *= d_bw / (2 * M_PI * d_freq * 80);
if(d_current_symbol < 2) {
d_prev_pilots[0] = current_symbol[11];
d_prev_pilots[1] = -current_symbol[25];
d_prev_pilots[2] = current_symbol[39];
d_prev_pilots[3] = current_symbol[53];
} else {
d_prev_pilots[0] = current_symbol[11] * p;
d_prev_pilots[1] = current_symbol[25] * p;
d_prev_pilots[2] = current_symbol[39] * p;
d_prev_pilots[3] = current_symbol[53] * -p;
}
// compensate residual frequency offset
for(int i = 0; i < 64; i++) {
current_symbol[i] *= exp(gr_complex(0, -beta));
}
// update estimate of residual frequency offset
if(d_current_symbol >= 2) {
double alpha = 0.1;
d_er = (1-alpha) * d_er + alpha * er;
}
// do equalization
d_equalizer->equalize(current_symbol, d_current_symbol,
symbols, out + o * 48, d_frame_mod);
// signal field
if(d_current_symbol == 2) {
if(decode_signal_field(out + o * 48)) {
pmt::pmt_t dict = pmt::make_dict();
dict = pmt::dict_add(dict, pmt::mp("frame_bytes"), pmt::from_uint64(d_frame_bytes));
dict = pmt::dict_add(dict, pmt::mp("encoding"), pmt::from_uint64(d_frame_encoding));
dict = pmt::dict_add(dict, pmt::mp("snr"), pmt::from_double(d_equalizer->get_snr()));
dict = pmt::dict_add(dict, pmt::mp("freq"), pmt::from_double(d_freq));
dict = pmt::dict_add(dict, pmt::mp("freq_offset"), pmt::from_double(d_freq_offset_from_synclong));
add_item_tag(0, nitems_written(0) + o,
pmt::string_to_symbol("wifi_start"),
dict,
pmt::string_to_symbol(alias()));
}
}
if(d_current_symbol > 2) {
o++;
pmt::pmt_t pdu = pmt::make_dict();
message_port_pub(pmt::mp("symbols"), pmt::cons(pmt::make_dict(), pmt::init_c32vector(48, symbols)));
}
i++;
d_current_symbol++;
}
consume(0, i);
return o;
}
bool
frame_equalizer_impl::decode_signal_field(uint8_t *rx_bits) {
static ofdm_param ofdm(BPSK_1_2);
static frame_param frame(ofdm, 0);
deinterleave(rx_bits);
uint8_t *decoded_bits = d_decoder.decode(&ofdm, &frame, d_deinterleaved);
return parse_signal(decoded_bits);
}
void
frame_equalizer_impl::deinterleave(uint8_t *rx_bits) {
for(int i = 0; i < 48; i++) {
d_deinterleaved[i] = rx_bits[interleaver_pattern[i]];
}
}
bool
frame_equalizer_impl::parse_signal(uint8_t *decoded_bits) {
int r = 0;
d_frame_bytes = 0;
bool parity = false;
for(int i = 0; i < 17; i++) {
parity ^= decoded_bits[i];
if((i < 4) && decoded_bits[i]) {
r = r | (1 << i);
}
if(decoded_bits[i] && (i > 4) && (i < 17)) {
d_frame_bytes = d_frame_bytes | (1 << (i-5));
}
}
if(parity != decoded_bits[17]) {
dout << "SIGNAL: wrong parity" << std::endl;
return false;
}
switch(r) {
case 11:
d_frame_encoding = 0;
d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 24);
d_frame_mod = d_bpsk;
dout << "Encoding: 3 Mbit/s ";
break;
case 15:
d_frame_encoding = 1;
d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 36);
d_frame_mod = d_bpsk;
dout << "Encoding: 4.5 Mbit/s ";
break;
case 10:
d_frame_encoding = 2;
d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 48);
d_frame_mod = d_qpsk;
dout << "Encoding: 6 Mbit/s ";
break;
case 14:
d_frame_encoding = 3;
d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 72);
d_frame_mod = d_qpsk;
dout << "Encoding: 9 Mbit/s ";
break;
case 9:
d_frame_encoding = 4;
d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 96);
d_frame_mod = d_16qam;
dout << "Encoding: 12 Mbit/s ";
break;
case 13:
d_frame_encoding = 5;
d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 144);
d_frame_mod = d_16qam;
dout << "Encoding: 18 Mbit/s ";
break;
case 8:
d_frame_encoding = 6;
d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 192);
d_frame_mod = d_64qam;
dout << "Encoding: 24 Mbit/s ";
break;
case 12:
d_frame_encoding = 7;
d_frame_symbols = (int) ceil((16 + 8 * d_frame_bytes + 6) / (double) 216);
d_frame_mod = d_64qam;
dout << "Encoding: 27 Mbit/s ";
break;
default:
dout << "unknown encoding" << std::endl;
return false;
}
mylog(boost::format("encoding: %1% - length: %2% - symbols: %3%")
% d_frame_encoding % d_frame_bytes % d_frame_symbols);
return true;
}
const int
frame_equalizer_impl::interleaver_pattern[48] = {
0, 3, 6, 9,12,15,18,21,
24,27,30,33,36,39,42,45,
1, 4, 7,10,13,16,19,22,
25,28,31,34,37,40,43,46,
2, 5, 8,11,14,17,20,23,
26,29,32,35,38,41,44,47};
} /* namespace ieee802_11 */
} /* namespace gr */
+88
View File
@@ -0,0 +1,88 @@
/*
* Copyright (C) 2016 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_IEEE802_11_FRAME_EQUALIZER_IMPL_H
#define INCLUDED_IEEE802_11_FRAME_EQUALIZER_IMPL_H
#include <ieee802-11/frame_equalizer.h>
#include <ieee802-11/constellations.h>
#include "equalizer/base.h"
#include "viterbi_decoder.h"
namespace gr {
namespace ieee802_11 {
class frame_equalizer_impl : virtual public frame_equalizer
{
public:
frame_equalizer_impl(Equalizer algo, double freq, double bw, bool log, bool debug);
~frame_equalizer_impl();
void set_algorithm(Equalizer algo);
void set_bandwidth(double bw);
void set_frequency(double freq);
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
private:
bool parse_signal(uint8_t *signal);
bool decode_signal_field(uint8_t *rx_bits);
void deinterleave(uint8_t *rx_bits);
equalizer::base *d_equalizer;
gr::thread::mutex d_mutex;
std::vector<gr::tag_t> tags;
bool d_debug;
bool d_log;
int d_current_symbol;
viterbi_decoder d_decoder;
// freq offset
double d_freq; // Hz
double d_freq_offset_from_synclong; // Hz, estimation from "sync_long" block
double d_bw; // Hz
double d_er;
double d_epsilon0;
gr_complex d_prev_pilots[4];
int d_frame_bytes;
int d_frame_symbols;
int d_frame_encoding;
uint8_t d_deinterleaved[48];
gr_complex symbols[48];
boost::shared_ptr<gr::digital::constellation> d_frame_mod;
constellation_bpsk::sptr d_bpsk;
constellation_qpsk::sptr d_qpsk;
constellation_16qam::sptr d_16qam;
constellation_64qam::sptr d_64qam;
static const int interleaver_pattern[48];
};
} // namespace ieee802_11
} // namespace gr
#endif /* INCLUDED_IEEE802_11_FRAME_EQUALIZER_IMPL_H */
+20 -39
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <ieee802-11/ofdm_mac.h> #include <ieee802-11/mac.h>
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
#include <gnuradio/block_detail.h> #include <gnuradio/block_detail.h>
@@ -34,12 +34,12 @@
using namespace gr::ieee802_11; using namespace gr::ieee802_11;
class ofdm_mac_impl : public ofdm_mac { class mac_impl : public mac {
public: public:
ofdm_mac_impl(std::vector<uint8_t> src_mac, std::vector<uint8_t> dst_mac, std::vector<uint8_t> bss_mac) : mac_impl(std::vector<uint8_t> src_mac, std::vector<uint8_t> dst_mac, std::vector<uint8_t> bss_mac) :
block("ofdm_mac", block("mac",
gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0)), gr::io_signature::make(0, 0, 0)),
d_seq_nr(0) { d_seq_nr(0) {
@@ -48,10 +48,10 @@ ofdm_mac_impl(std::vector<uint8_t> src_mac, std::vector<uint8_t> dst_mac, std::v
message_port_register_out(pmt::mp("app out")); message_port_register_out(pmt::mp("app out"));
message_port_register_in(pmt::mp("app in")); message_port_register_in(pmt::mp("app in"));
set_msg_handler(pmt::mp("app in"), boost::bind(&ofdm_mac_impl::app_in, this, _1)); set_msg_handler(pmt::mp("app in"), boost::bind(&mac_impl::app_in, this, _1));
message_port_register_in(pmt::mp("phy in")); message_port_register_in(pmt::mp("phy in"));
set_msg_handler(pmt::mp("phy in"), boost::bind(&ofdm_mac_impl::phy_in, this, _1)); set_msg_handler(pmt::mp("phy in"), boost::bind(&mac_impl::phy_in, this, _1));
if(!check_mac(src_mac)) throw std::invalid_argument("wrong mac address size"); if(!check_mac(src_mac)) throw std::invalid_argument("wrong mac address size");
if(!check_mac(dst_mac)) throw std::invalid_argument("wrong mac address size"); if(!check_mac(dst_mac)) throw std::invalid_argument("wrong mac address size");
@@ -66,8 +66,9 @@ ofdm_mac_impl(std::vector<uint8_t> src_mac, std::vector<uint8_t> dst_mac, std::v
void phy_in (pmt::pmt_t msg) { void phy_in (pmt::pmt_t msg) {
// this must be a pair // this must be a pair
if (!pmt::is_blob(pmt::cdr(msg))) if (!pmt::is_blob(pmt::cdr(msg))) {
throw std::runtime_error("PMT must be blob"); throw std::runtime_error("PMT must be blob");
}
// strip MAC header // strip MAC header
// TODO: check for frame type to determine header size // TODO: check for frame type to determine header size
@@ -83,34 +84,25 @@ void app_in (pmt::pmt_t msg) {
size_t msg_len; size_t msg_len;
const char *msdu; const char *msdu;
std::string str;
// dict if(pmt::is_symbol(msg)) {
pmt::pmt_t dict = pmt::make_dict();
if(pmt::is_eof_object(msg)) {
message_port_pub(pmt::mp("phy out"), pmt::PMT_EOF);
detail().get()->set_done(true);
return;
} else if(pmt::is_symbol(msg)) {
std::string str;
str = pmt::symbol_to_string(msg); str = pmt::symbol_to_string(msg);
msg_len = str.length(); msg_len = str.length();
msdu = str.data(); msdu = str.data();
} else if(pmt::is_pair(msg)) { } else if(pmt::is_pair(msg)) {
dict = pmt::car(msg);
msg_len = pmt::blob_length(pmt::cdr(msg)); msg_len = pmt::blob_length(pmt::cdr(msg));
msdu = reinterpret_cast<const char *>(pmt::blob_data(pmt::cdr(msg))); msdu = reinterpret_cast<const char *>(pmt::blob_data(pmt::cdr(msg)));
} else { } else {
throw std::invalid_argument("OFDM MAC expects PDUs or strings"); throw std::invalid_argument("MAC expects PDUs or strings");
return; return;
} }
if(msg_len > 1500) { if(msg_len > MAX_PAYLOAD_SIZE) {
throw std::invalid_argument("Frame too large (> 1500)"); throw std::invalid_argument("Frame too large (> 1500)");
} }
@@ -118,21 +110,10 @@ void app_in (pmt::pmt_t msg) {
int psdu_length; int psdu_length;
generate_mac_data_frame(msdu, msg_len, &psdu_length); generate_mac_data_frame(msdu, msg_len, &psdu_length);
// dict
pmt::pmt_t dict = pmt::make_dict();
dict = pmt::dict_add(dict, pmt::mp("crc_included"), pmt::PMT_T); dict = pmt::dict_add(dict, pmt::mp("crc_included"), pmt::PMT_T);
// check if csma is enabled
pmt::pmt_t pmt_cw = pmt::dict_ref(dict, pmt::mp("cw_min"), pmt::PMT_NIL);
if(pmt_cw != pmt::PMT_NIL) {
uint64_t cw = pmt::to_long(pmt_cw);
pmt::pmt_t backoffs = pmt::make_u64vector(2, 0);
pmt::u64vector_set(backoffs, 0, rand() % cw);
pmt::u64vector_set(backoffs, 1, rand() % cw);
dict = pmt::dict_add(dict, pmt::mp("backoffs"), backoffs);
dict = pmt::dict_add(dict, pmt::mp("csma"), pmt::PMT_T);
}
// blob // blob
pmt::pmt_t mac = pmt::make_blob(d_psdu, psdu_length); pmt::pmt_t mac = pmt::make_blob(d_psdu, psdu_length);
@@ -187,11 +168,11 @@ private:
uint8_t d_src_mac[6]; uint8_t d_src_mac[6];
uint8_t d_dst_mac[6]; uint8_t d_dst_mac[6];
uint8_t d_bss_mac[6]; uint8_t d_bss_mac[6];
uint8_t d_psdu[1528]; uint8_t d_psdu[MAX_PSDU_SIZE];
}; };
ofdm_mac::sptr mac::sptr
ofdm_mac::make(std::vector<uint8_t> src_mac, std::vector<uint8_t> dst_mac, std::vector<uint8_t> bss_mac) { mac::make(std::vector<uint8_t> src_mac, std::vector<uint8_t> dst_mac, std::vector<uint8_t> bss_mac) {
return gnuradio::get_initial_sptr(new ofdm_mac_impl(src_mac, dst_mac, bss_mac)); return gnuradio::get_initial_sptr(new mac_impl(src_mac, dst_mac, bss_mac));
} }
+42 -49
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,39 +14,40 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <ieee802-11/ofdm_mapper.h> #include <ieee802-11/mapper.h>
#include "utils.h" #include "utils.h"
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
using namespace gr::ieee802_11; using namespace gr::ieee802_11;
class ofdm_mapper_impl : public ofdm_mapper { class mapper_impl : public mapper {
public: public:
static const int DATA_CARRIERS = 48; static const int DATA_CARRIERS = 48;
ofdm_mapper_impl(Encoding e, bool debug) : mapper_impl(Encoding e, bool debug) :
block ("ofdm_mapper", block ("mapper",
gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0),
gr::io_signature::make(1, 1, sizeof(char))), gr::io_signature::make(1, 1, sizeof(char))),
d_symbols_offset(0), d_symbols_offset(0),
d_symbols(NULL), d_symbols(NULL),
d_debug(debug), d_debug(debug),
d_scrambler(1),
d_ofdm(e) { d_ofdm(e) {
message_port_register_in(pmt::mp("in")); message_port_register_in(pmt::mp("in"));
set_encoding(e); set_encoding(e);
} }
~ofdm_mapper_impl() { ~mapper_impl() {
free(d_symbols); free(d_symbols);
} }
void print_message(const char *msg, size_t len) { void print_message(const char *msg, size_t len) {
dout << std::hex << "OFDM MAPPER input symbols" << std::endl dout << std::hex << "MAPPER input symbols" << std::endl
<< "===========================" << std::endl; << "===========================" << std::endl;
for(int i = 0; i < len; i++) { for(int i = 0; i < len; i++) {
@@ -62,63 +63,62 @@ int general_work(int noutput, gr_vector_int& ninput_items,
gr_vector_void_star& output_items ) { gr_vector_void_star& output_items ) {
unsigned char *out = (unsigned char*)output_items[0]; unsigned char *out = (unsigned char*)output_items[0];
dout << "OFDM MAPPER called offset: " << d_symbols_offset << dout << "MAPPER called offset: " << d_symbols_offset <<
" length: " << d_symbols_len << std::endl; " length: " << d_symbols_len << std::endl;
while(!d_symbols_offset) { while(!d_symbols_offset) {
pmt::pmt_t msg(delete_head_blocking(pmt::intern("in"))); pmt::pmt_t msg(delete_head_nowait(pmt::intern("in")));
if(pmt::is_eof_object(msg)) { if(!msg.get()) {
dout << "MAPPER: exiting" << std::endl; return 0;
return -1; }
}
if(pmt::is_pair(msg)) { if(pmt::is_pair(msg)) {
dout << "OFDM MAPPER: received new message" << std::endl; dout << "MAPPER: received new message" << std::endl;
gr::thread::scoped_lock lock(d_mutex); gr::thread::scoped_lock lock(d_mutex);
int psdu_length = pmt::blob_length(pmt::cdr(msg)); int psdu_length = pmt::blob_length(pmt::cdr(msg));
const char *psdu = static_cast<const char*>(pmt::blob_data(pmt::cdr(msg))); const char *psdu = static_cast<const char*>(pmt::blob_data(pmt::cdr(msg)));
// ############ INSERT MAC STUFF // ############ INSERT MAC STUFF
tx_param tx(d_ofdm, psdu_length); frame_param frame(d_ofdm, psdu_length);
if(tx.n_sym > MAX_SYM) { if(frame.n_sym > MAX_SYM) {
std::cout << "packet too large, maximum number of symbols is " << MAX_SYM << std::endl; std::cout << "packet too large, maximum number of symbols is " << MAX_SYM << std::endl;
return 0; return 0;
} }
//alloc memory for modulation steps //alloc memory for modulation steps
char *data_bits = (char*)calloc(tx.n_data, sizeof(char)); char *data_bits = (char*)calloc(frame.n_data_bits, sizeof(char));
char *scrambled_data = (char*)calloc(tx.n_data, sizeof(char)); char *scrambled_data = (char*)calloc(frame.n_data_bits, sizeof(char));
char *encoded_data = (char*)calloc(tx.n_data * 2, sizeof(char)); char *encoded_data = (char*)calloc(frame.n_data_bits * 2, sizeof(char));
char *punctured_data = (char*)calloc(tx.n_encoded_bits, sizeof(char)); char *punctured_data = (char*)calloc(frame.n_encoded_bits, sizeof(char));
char *interleaved_data = (char*)calloc(tx.n_encoded_bits, sizeof(char)); char *interleaved_data = (char*)calloc(frame.n_encoded_bits, sizeof(char));
char *symbols = (char*)calloc((tx.n_encoded_bits / d_ofdm.n_bpsc), sizeof(char)); char *symbols = (char*)calloc((frame.n_encoded_bits / d_ofdm.n_bpsc), sizeof(char));
//generate the OFDM data field, adding service field and pad bits //generate the WIFI data field, adding service field and pad bits
generate_bits(psdu, data_bits, tx); generate_bits(psdu, data_bits, frame);
//print_hex_array(data_bits, tx.n_data);
// scrambling
scramble(data_bits, scrambled_data, frame, d_scrambler++);
if(d_scrambler > 127) {
d_scrambler = 1;
}
// first step, scrambling
scramble(data_bits, scrambled_data, tx, 23);
//print_hex_array(scrambled_data, tx.n_data);
// reset tail bits // reset tail bits
reset_tail_bits(scrambled_data, tx); reset_tail_bits(scrambled_data, frame);
//print_hex_array(scrambled_data, tx.n_data);
// encoding // encoding
convolutional_encoding(scrambled_data, encoded_data, tx); convolutional_encoding(scrambled_data, encoded_data, frame);
//print_hex_array(encoded_data, tx.n_data * 2);
// puncturing // puncturing
puncturing(encoded_data, punctured_data, tx, d_ofdm); puncturing(encoded_data, punctured_data, frame, d_ofdm);
//std::cout << "punctured" << std::endl; //std::cout << "punctured" << std::endl;
// interleaving // interleaving
interleave(punctured_data, interleaved_data, tx, d_ofdm); interleave(punctured_data, interleaved_data, frame, d_ofdm);
//std::cout << "interleaved" << std::endl; //std::cout << "interleaved" << std::endl;
// one byte per symbol // one byte per symbol
split_symbols(interleaved_data, symbols, tx, d_ofdm); split_symbols(interleaved_data, symbols, frame, d_ofdm);
d_symbols_len = tx.n_sym * 48; d_symbols_len = frame.n_sym * 48;
d_symbols = (char*)calloc(d_symbols_len, 1); d_symbols = (char*)calloc(d_symbols_len, 1);
std::memcpy(d_symbols, symbols, d_symbols_len); std::memcpy(d_symbols, symbols, d_symbols_len);
@@ -138,14 +138,6 @@ int general_work(int noutput, gr_vector_int& ninput_items,
add_item_tag(0, nitems_written(0), pmt::mp("encoding"), add_item_tag(0, nitems_written(0), pmt::mp("encoding"),
encoding, srcid); encoding, srcid);
pmt::pmt_t dict_items(pmt::dict_items(pmt::car(msg)));
while (!pmt::is_null(dict_items)) {
pmt::pmt_t this_item(pmt::car(dict_items));
add_item_tag(0, nitems_written(0), pmt::car(this_item),
pmt::cdr(this_item), srcid);
dict_items = pmt::cdr(dict_items);
}
free(data_bits); free(data_bits);
free(scrambled_data); free(scrambled_data);
@@ -173,13 +165,14 @@ int general_work(int noutput, gr_vector_int& ninput_items,
void set_encoding(Encoding encoding) { void set_encoding(Encoding encoding) {
std::cout << "OFDM MAPPER: encoding: " << encoding << std::endl; std::cout << "MAPPER: encoding: " << encoding << std::endl;
gr::thread::scoped_lock lock(d_mutex); gr::thread::scoped_lock lock(d_mutex);
d_ofdm = ofdm_param(encoding); d_ofdm = ofdm_param(encoding);
} }
private: private:
uint8_t d_scrambler;
bool d_debug; bool d_debug;
char* d_symbols; char* d_symbols;
int d_symbols_offset; int d_symbols_offset;
@@ -188,7 +181,7 @@ private:
gr::thread::mutex d_mutex; gr::thread::mutex d_mutex;
}; };
ofdm_mapper::sptr mapper::sptr
ofdm_mapper::make(Encoding mcs, bool debug) { mapper::make(Encoding mcs, bool debug) {
return gnuradio::get_initial_sptr(new ofdm_mapper_impl(mcs, debug)); return gnuradio::get_initial_sptr(new mapper_impl(mcs, debug));
} }
-332
View File
@@ -1,332 +0,0 @@
/*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ieee802-11/ofdm_decode_mac.h>
#include "utils.h"
#include <boost/crc.hpp>
#include <gnuradio/io_signature.h>
#include <itpp/itcomm.h>
#include <iomanip>
using namespace gr::ieee802_11;
using namespace itpp;
class ofdm_decode_mac_impl : public ofdm_decode_mac {
public:
ofdm_decode_mac_impl(bool log, bool debug) : block("ofdm_decode_mac",
gr::io_signature::make(1, 1, 48 * sizeof(gr_complex)),
gr::io_signature::make(0, 0, 0)),
d_log(log),
d_debug(debug),
d_ofdm(BPSK_1_2),
d_tx(d_ofdm, 0),
d_frame_complete(true) {
message_port_register_out(pmt::mp("out"));
// bpsk
int bpsk_bits[] = {0, 1};
bpsk.set(cvec(BPSK_D, 2), ivec(bpsk_bits, 2));
// qpsk
int qpsk_bits[] = {0, 1, 2, 3};
qpsk.set(cvec(QPSK_D, 4), ivec(qpsk_bits, 4));
// qam16
int qam16_bits[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
qam16.set(cvec(QAM16_D, 16), ivec(qam16_bits, 16));
// qam64
int qam64_bits[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63};
qam64.set(cvec(QAM64_D, 64), ivec(qam64_bits, 64));
}
int general_work (int noutput_items, gr_vector_int& ninput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items) {
const gr_complex *in = (const gr_complex*)input_items[0];
int i = 0;
std::vector<gr::tag_t> tags;
const uint64_t nread = this->nitems_read(0);
dout << "Decode MAC: input " << ninput_items[0] << std::endl;
while(i < ninput_items[0]) {
get_tags_in_range(tags, 0, nread + i, nread + i + 1,
pmt::string_to_symbol("ofdm_start"));
if(tags.size()) {
if (d_frame_complete == false) {
dout << "Warning: starting to receive new frame before old frame was complete" << std::endl;
dout << "Already copied " << copied << " out of " << d_tx.n_sym << " symbols of last frame" << std::endl;
}
d_frame_complete = false;
pmt::pmt_t tuple = tags[0].value;
int len_data = pmt::to_uint64(pmt::car(tuple));
int encoding = pmt::to_uint64(pmt::cdr(tuple));
ofdm_param ofdm = ofdm_param((Encoding)encoding);
tx_param tx = tx_param(ofdm, len_data);
// sanity check, more than MAX_SYM may indicate garbage
if(tx.n_sym <= MAX_SYM && tx.n_encoded_bits <= MAX_BITS) {
d_ofdm = ofdm;
d_tx = tx;
copied = 0;
dout << "Decode MAC: frame start -- len " << len_data
<< " symbols " << tx.n_sym << " encoding "
<< encoding << std::endl;
} else {
dout << "Dropping frame which is too large (symbols or bits)" << std::endl;
}
}
if(copied < d_tx.n_sym) {
dout << "copy one symbol, copied " << copied << " out of " << d_tx.n_sym << std::endl;
std::memcpy(sym + (copied * 48), in, 48 * sizeof(gr_complex));
copied++;
if(copied == d_tx.n_sym) {
dout << "received complete frame - decoding" << std::endl;
decode();
in += 48;
i++;
d_frame_complete = true;
break;
}
}
in += 48;
i++;
}
consume(0, i);
return 0;
}
void decode() {
demodulate();
deinterleave();
decode_conv();
descramble();
print_output();
// skip service field
boost::crc_32_type result;
result.process_bytes(out_bytes + 2, d_tx.psdu_size);
if(result.checksum() != 558161692) {
dout << "checksum wrong -- dropping" << std::endl;
return;
}
mylog(boost::format("encoding: %1% - length: %2% - symbols: %3%")
% d_ofdm.encoding % d_tx.psdu_size % d_tx.n_sym);
// create PDU
pmt::pmt_t blob = pmt::make_blob(out_bytes + 2, d_tx.psdu_size - 4);
pmt::pmt_t enc = pmt::from_uint64(d_ofdm.encoding);
pmt::pmt_t dict = pmt::make_dict();
dict = pmt::dict_add(dict, pmt::mp("encoding"), enc);
message_port_pub(pmt::mp("out"), pmt::cons(dict, blob));
}
void demodulate() {
cvec symbols;
symbols.set_length(d_tx.n_sym * 48);
for(int i = 0; i < d_tx.n_sym * 48; i++) {
symbols[i] = std::complex<double>(sym[i]);
}
switch(d_ofdm.encoding) {
case BPSK_1_2:
case BPSK_3_4:
bits = to_vec(bpsk.demodulate_bits(symbols));
break;
case QPSK_1_2:
case QPSK_3_4:
bits = to_vec(qpsk.demodulate_bits(symbols));
break;
case QAM16_1_2:
case QAM16_3_4:
bits = to_vec(qam16.demodulate_bits(symbols));
break;
case QAM64_2_3:
case QAM64_3_4:
bits = to_vec(qam64.demodulate_bits(symbols));
break;
}
// I hate the guy who wrote itpp
bits = bits * (-2) + 1;
}
void deinterleave() {
int n_cbps = d_ofdm.n_cbps;
int first[n_cbps];
int second[n_cbps];
int s = std::max(d_ofdm.n_bpsc / 2, 1);
for(int j = 0; j < n_cbps; j++) {
first[j] = s * (j / s) + ((j + int(floor(16.0 * j / n_cbps))) % s);
}
for(int i = 0; i < n_cbps; i++) {
second[i] = 16 * i - (n_cbps - 1) * int(floor(16.0 * i / n_cbps));
}
for(int i = 0; i < d_tx.n_sym; i++) {
for(int k = 0; k < n_cbps; k++) {
deinter[i * n_cbps + second[first[k]]] = bits[i * n_cbps + k];
}
}
}
void decode_conv() {
Punctured_Convolutional_Code code;
ivec generator(2);
generator(0)=0133;
generator(1)=0171;
code.set_generator_polynomials(generator, 7);
bmat puncture_matrix;
switch(d_ofdm.encoding) {
case BPSK_1_2:
case QPSK_1_2:
case QAM16_1_2:
puncture_matrix = "1 1; 1 1";
break;
case BPSK_3_4:
case QPSK_3_4:
case QAM16_3_4:
case QAM64_3_4:
puncture_matrix = "1 1 0; 1 0 1;";
break;
case QAM64_2_3:
puncture_matrix = "1 1 1 1 1 1; 1 0 1 0 1 0;";
break;
}
code.set_puncture_matrix(puncture_matrix);
code.set_truncation_length(30);
dout << "coding rate " << code.get_rate() << std::endl;
dout << d_tx.n_encoded_bits << std::endl;
vec rx_signal(deinter, d_tx.n_encoded_bits);
code.reset();
decoded_bits.set_length(d_tx.n_encoded_bits);
code.decode_tail(rx_signal, decoded_bits);
//dout << "length decoded " << decoded_bits.size() << std::endl;
//std::cout << decoded_bits << std::endl;
}
void descramble () {
int state = 0;
for(int i = 0; i < 7; i++) {
if(decoded_bits(i)) {
state |= 1 << (6 - i);
}
}
int feedback;
for(int i = 7; i < decoded_bits.size(); i++) {
feedback = ((!!(state & 64))) ^ (!!(state & 8));
out_bits[i] = feedback ^ (int)decoded_bits(i);
state = ((state << 1) & 0x7e) | feedback;
}
for(int i = 0; i < decoded_bits.size(); i++) {
int bit = i % 8;
int byte = i / 8;
if(bit == 0) {
out_bytes[byte] = 0;
}
if(out_bits[i]) {
out_bytes[byte] |= (1 << bit);
}
}
}
void print_output() {
dout << std::endl;
for(int i = 0; i < decoded_bits.size() / 8; i++) {
dout << std::setfill('0') << std::setw(2) << std::hex << ((unsigned int)out_bytes[i] & 0xFF) << std::dec << " ";
if(i % 16 == 15) {
dout << std::endl;
}
}
dout << std::endl;
for(int i = 0; i < decoded_bits.size() / 8; i++) {
if((out_bytes[i] > 31) && (out_bytes[i] < 127)) {
dout << ((char) out_bytes[i]);
} else {
dout << ".";
}
}
dout << std::endl;
}
private:
gr_complex sym[1000 * 48 * 100];
vec bits;
double deinter[1000 * 48];
char out_bits[40000];
char out_bytes[40000];
bvec decoded_bits;
bool d_debug;
bool d_log;
tx_param d_tx;
ofdm_param d_ofdm;
int copied;
bool d_frame_complete;
Modulator<std::complex<double> > bpsk;
Modulator<std::complex<double> > qpsk;
Modulator<std::complex<double> > qam16;
Modulator<std::complex<double> > qam64;
};
ofdm_decode_mac::sptr
ofdm_decode_mac::make(bool log, bool debug) {
return gnuradio::get_initial_sptr(new ofdm_decode_mac_impl(log, debug));
}
-222
View File
@@ -1,222 +0,0 @@
/*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ieee802-11/ofdm_decode_signal.h>
#include <gnuradio/io_signature.h>
#include "utils.h"
#include <itpp/itcomm.h>
using namespace gr::ieee802_11;
using namespace itpp;
class ofdm_decode_signal_impl : public ofdm_decode_signal {
public:
ofdm_decode_signal_impl(bool log, bool debug) : block("ofdm_decode_signal",
gr::io_signature::make(1, 1, 48 * sizeof(gr_complex)),
gr::io_signature::make(1, 1, 48 * sizeof(gr_complex))),
d_log(log),
d_debug(debug),
d_copy_symbols(0) {
decoded_bits.set_size(24);
set_relative_rate(1);
set_tag_propagation_policy(block::TPP_DONT);
}
~ofdm_decode_signal_impl(){
}
int general_work (int noutput_items, gr_vector_int& ninput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items) {
const gr_complex *in = (const gr_complex*)input_items[0];
gr_complex *out = (gr_complex*)output_items[0];
int i = 0;
int o = 0;
std::vector<gr::tag_t> tags;
const uint64_t nread = nitems_read(0);
dout << "Decode Signal: input " << ninput_items[0]
<< " output " << noutput_items << std::endl;
while((i < ninput_items[0]) && (o < noutput_items)) {
get_tags_in_range(tags, 0, nread + i, nread + i + 1,
pmt::string_to_symbol("ofdm_start"));
if(tags.size()) {
for(int n = 0; n < 48; n++) {
bits[n] = -real(in[n]);
}
deinterleave();
decode();
if(print_signal()) {
add_item_tag(0, nitems_written(0) + o * 48,
pmt::string_to_symbol("ofdm_start"),
pmt::cons(pmt::from_uint64(d_len),
pmt::from_uint64(d_encoding)),
pmt::string_to_symbol(name()));
}
} else if(d_copy_symbols) {
std::memcpy(out, in, 48 * sizeof(gr_complex));
o++;
out += 48;
d_copy_symbols--;
}
in += 48;
i++;
}
dout << "Decode Signal consumed " << i <<
" produced " << o << std::endl;
consume(0, i);
return o;
}
void deinterleave() {
double tmp[48];
for(int i = 0; i < 48; i++) {
tmp[i] = bits[inter[i]];
}
for(int i = 0; i < 48; i++) {
bits[i] = tmp[i];
}
for(int i = 0; i < 48; i++) {
dout << bits[i] << " ";
}
dout << std::endl;
}
void decode() {
Convolutional_Code code;
ivec generator(2);
generator(0)=0133;
generator(1)=0171;
code.set_generator_polynomials(generator, 7);
code.set_truncation_length(30);
vec rx_signal(bits, 48);
code.reset();
code.decode_tail(rx_signal, decoded_bits);
dout << "length rx " << rx_signal.size() << std::endl;
dout << rx_signal << std::endl;
dout << "length decoded " << decoded_bits.size() << std::endl;
dout << decoded_bits << std::endl;
}
bool print_signal() {
int r = 0;
d_len = 0;
bool parity = false;
for(int i = 0; i < 17; i++) {
parity ^= (bool)decoded_bits[i];
if((i < 4) && decoded_bits[i]) {
r = r | (1 << i);
}
if(decoded_bits[i] && (i > 4) && (i < 17)) {
d_len = d_len | (1 << (i-5));
}
}
if(parity != (bool)decoded_bits[17]) {
dout << "SIGNAL: wrong parity" << std::endl;
return false;
}
if(r == 11) {
d_encoding = 0;
d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 24);
dout << "Encoding: 3 Mbit/s ";
} else if(r == 15) {
d_encoding = 1;
d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 36);
dout << "Encoding: 4.5 Mbit/s ";
} else if(r == 10) {
d_encoding = 2;
d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 48);
dout << "Encoding: 6 Mbit/s ";
} else if(r == 14) {
d_encoding = 3;
d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 72);
dout << "Encoding: 9 Mbit/s ";
} else if(r == 9) {
d_encoding = 4;
d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 96);
dout << "Encoding: 12 Mbit/s ";
} else if(r == 13) {
d_encoding = 5;
d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 144);
dout << "Encoding: 18 Mbit/s ";
} else if(r == 8) {
d_encoding = 6;
d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 192);
dout << "Encoding: 24 Mbit/s ";
} else if(r == 12) {
d_encoding = 7;
d_copy_symbols = (int) ceil((16 + 8 * d_len + 6) / (double) 216);
dout << "Encoding: 27 Mbit/s ";
} else {
dout << "unknown encoding" << std::endl;
return false;
}
mylog(boost::format("encoding: %1% - length: %2% - symbols: %3%")
% d_encoding % d_len % d_copy_symbols);
dout << "d_copy_symbols: " << d_copy_symbols << std::endl;
dout << "length: " << d_len << std::endl;
return true;
}
private:
int d_len;
int d_encoding;
bool d_log;
bool d_debug;
double bits[48];
int d_copy_symbols;
bvec decoded_bits;
static int inter[48];
};
ofdm_decode_signal::sptr
ofdm_decode_signal::make(bool log, bool debug) {
return gnuradio::get_initial_sptr(new ofdm_decode_signal_impl(log, debug));
}
int ofdm_decode_signal_impl::inter[48]={0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,1,4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,2,5,8,11,14,17,20,23,26,29,32,35,38,41,44,47};
-120
View File
@@ -1,120 +0,0 @@
/*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ieee802-11/ofdm_equalize_symbols.h>
#include "utils.h"
#include "equalizer/base.h"
#include "equalizer/linear_comb.h"
#include "equalizer/lms.h"
#include <gnuradio/io_signature.h>
using namespace gr::ieee802_11;
class ofdm_equalize_symbols_impl : public ofdm_equalize_symbols {
public:
ofdm_equalize_symbols_impl(Equalizer algo, bool debug) : block("ofdm_equalize_symbols",
gr::io_signature::make(1, 1, 64 * sizeof(gr_complex)),
gr::io_signature::make(1, 1, 48 * sizeof(gr_complex))),
d_debug(debug), d_equalizer(NULL) {
set_relative_rate(1);
set_tag_propagation_policy(block::TPP_DONT);
set_algorithm(algo);
}
~ofdm_equalize_symbols_impl(){
}
int general_work (int noutput_items, gr_vector_int& ninput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items) {
gr::thread::scoped_lock lock(d_mutex);
const gr_complex *in = (const gr_complex*)input_items[0];
gr_complex *out = (gr_complex*)output_items[0];
int i = 0;
int o = 0;
dout << "SYMBOLS: input " << ninput_items[0] << " output " << noutput_items << std::endl;
while((i < ninput_items[0]) && (o < noutput_items)) {
get_tags_in_window(tags, 0, i, i + 1, pmt::string_to_symbol("ofdm_start"));
// new WiFi frame
if(tags.size()) {
d_nsym = 0;
}
// first data symbol (= signal field)
if(d_nsym == 2) {
add_item_tag(0, nitems_written(0) + o,
pmt::string_to_symbol("ofdm_start"),
pmt::PMT_T,
pmt::string_to_symbol(name()));
}
d_equalizer->equalize(in + (i * 64), out + (o * 48), d_nsym);
if(d_nsym > 1) {
o++;
}
i++;
d_nsym++;
}
dout << "SYMBOLS: consumed " << i << " produced " << o << std::endl;
consume(0, i);
return o;
}
void set_algorithm(Equalizer algo) {
gr::thread::scoped_lock lock(d_mutex);
delete d_equalizer;
switch(algo) {
case LMS:
dout << "LMS" << std::endl;
d_equalizer = new equalizer::lms();
break;
case LINEAR_COMB:
dout << "Linear Comb" << std::endl;
d_equalizer = new equalizer::linear_comb();
break;
}
}
private:
int d_nsym;
const bool d_debug;
equalizer::base *d_equalizer;
std::vector<gr::tag_t> tags;
gr::thread::mutex d_mutex;
};
ofdm_equalize_symbols::sptr
ofdm_equalize_symbols::make(Equalizer algo, bool debug) {
return gnuradio::get_initial_sptr(new ofdm_equalize_symbols_impl(algo, debug));
}
+10 -10
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <ieee802-11/ofdm_parse_mac.h> #include <ieee802-11/parse_mac.h>
#include "utils.h" #include "utils.h"
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
@@ -23,24 +23,24 @@
using namespace gr::ieee802_11; using namespace gr::ieee802_11;
class ofdm_parse_mac_impl : public ofdm_parse_mac { class parse_mac_impl : public parse_mac {
public: public:
ofdm_parse_mac_impl(bool log, bool debug) : parse_mac_impl(bool log, bool debug) :
block("ofdm_parse_mac", block("parse_mac",
gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0)), gr::io_signature::make(0, 0, 0)),
d_log(log), d_last_seq_no(-1), d_log(log), d_last_seq_no(-1),
d_debug(debug) { d_debug(debug) {
message_port_register_in(pmt::mp("in")); message_port_register_in(pmt::mp("in"));
set_msg_handler(pmt::mp("in"), boost::bind(&ofdm_parse_mac_impl::parse, this, _1)); set_msg_handler(pmt::mp("in"), boost::bind(&parse_mac_impl::parse, this, _1));
message_port_register_out(pmt::mp("fer")); message_port_register_out(pmt::mp("fer"));
} }
~ofdm_parse_mac_impl() { ~parse_mac_impl() {
} }
@@ -358,9 +358,9 @@ private:
int d_last_seq_no; int d_last_seq_no;
}; };
ofdm_parse_mac::sptr parse_mac::sptr
ofdm_parse_mac::make(bool log, bool debug) { parse_mac::make(bool log, bool debug) {
return gnuradio::get_initial_sptr(new ofdm_parse_mac_impl(log, debug)); return gnuradio::get_initial_sptr(new parse_mac_impl(log, debug));
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -15,32 +15,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "wifi_signal_field_impl.h" #include "signal_field_impl.h"
#include "utils.h" #include "utils.h"
#include <gnuradio/digital/lfsr.h> #include <gnuradio/digital/lfsr.h>
using namespace gr::ieee802_11; using namespace gr::ieee802_11;
wifi_signal_field::sptr signal_field::sptr
wifi_signal_field::make() { signal_field::make() {
return wifi_signal_field::sptr(new wifi_signal_field_impl()); return signal_field::sptr(new signal_field_impl());
} }
wifi_signal_field::wifi_signal_field() : packet_header_default(48, "packet_len") {}; signal_field::signal_field() : packet_header_default(48, "packet_len") {};
wifi_signal_field_impl::wifi_signal_field_impl() : packet_header_default(48, "packet_len") {} signal_field_impl::signal_field_impl() : packet_header_default(48, "packet_len") {}
wifi_signal_field_impl::~wifi_signal_field_impl() {} signal_field_impl::~signal_field_impl() {}
int wifi_signal_field_impl::get_bit(int b, int i) { int signal_field_impl::get_bit(int b, int i) {
return (b & (1 << i) ? 1 : 0); return (b & (1 << i) ? 1 : 0);
} }
void wifi_signal_field_impl::generate_signal_field(char *out, tx_param &tx, ofdm_param &ofdm) { void signal_field_impl::generate_signal_field(char *out, frame_param &frame, ofdm_param &ofdm) {
//data bits of the signal header //data bits of the signal header
char *signal_header = (char *) malloc(sizeof(char) * 24); char *signal_header = (char *) malloc(sizeof(char) * 24);
@@ -51,7 +51,7 @@ void wifi_signal_field_impl::generate_signal_field(char *out, tx_param &tx, ofdm
//interleaving //interleaving
char *interleaved_signal_header = (char *) malloc(sizeof(char) * 48); char *interleaved_signal_header = (char *) malloc(sizeof(char) * 48);
int length = tx.psdu_size; int length = frame.psdu_size;
// first 4 bits represent the modulation and coding scheme // first 4 bits represent the modulation and coding scheme
signal_header[ 0] = get_bit(ofdm.rate_field, 3); signal_header[ 0] = get_bit(ofdm.rate_field, 3);
@@ -88,22 +88,19 @@ void wifi_signal_field_impl::generate_signal_field(char *out, tx_param &tx, ofdm
} }
ofdm_param signal_ofdm(BPSK_1_2); ofdm_param signal_ofdm(BPSK_1_2);
tx_param signal_tx(signal_ofdm, 3); frame_param signal_param(signal_ofdm, 0);
signal_tx.n_data = 24;
signal_tx.n_sym = 1;
// convolutional encoding (scrambling is not needed) // convolutional encoding (scrambling is not needed)
convolutional_encoding(signal_header, encoded_signal_header, signal_tx); convolutional_encoding(signal_header, encoded_signal_header, signal_param);
// interleaving // interleaving
//interleave(encoded_signal_header, interleaved_signal_header, signal_tx, signal_ofdm); interleave(encoded_signal_header, out, signal_param, signal_ofdm);
interleave(encoded_signal_header, out, signal_tx, signal_ofdm);
free(signal_header); free(signal_header);
free(encoded_signal_header); free(encoded_signal_header);
free(interleaved_signal_header); free(interleaved_signal_header);
} }
bool wifi_signal_field_impl::header_formatter(long packet_len, unsigned char *out, const std::vector<tag_t> &tags) bool signal_field_impl::header_formatter(long packet_len, unsigned char *out, const std::vector<tag_t> &tags)
{ {
bool encoding_found = false; bool encoding_found = false;
@@ -128,13 +125,13 @@ bool wifi_signal_field_impl::header_formatter(long packet_len, unsigned char *ou
} }
ofdm_param ofdm((Encoding)encoding); ofdm_param ofdm((Encoding)encoding);
tx_param tx(ofdm, len); frame_param frame(ofdm, len);
generate_signal_field((char*)out, tx, ofdm); generate_signal_field((char*)out, frame, ofdm);
return true; return true;
} }
bool wifi_signal_field_impl::header_parser( bool signal_field_impl::header_parser(
const unsigned char *in, std::vector<tag_t> &tags) { const unsigned char *in, std::vector<tag_t> &tags) {
throw std::runtime_error("not implemented yet"); throw std::runtime_error("not implemented yet");
@@ -15,20 +15,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_WIFI_SIGNAL_FIELD_IMPL_H #ifndef INCLUDED_IEEE802_11_SIGNAL_FIELD_IMPL_H
#define INCLUDED_IEEE802_11_WIFI_SIGNAL_FIELD_IMPL_H #define INCLUDED_IEEE802_11_SIGNAL_FIELD_IMPL_H
#include <ieee802-11/wifi_signal_field.h> #include <ieee802-11/signal_field.h>
#include "utils.h" #include "utils.h"
namespace gr { namespace gr {
namespace ieee802_11 { namespace ieee802_11 {
class wifi_signal_field_impl : public wifi_signal_field class signal_field_impl : public signal_field
{ {
public: public:
wifi_signal_field_impl(); signal_field_impl();
~wifi_signal_field_impl(); ~signal_field_impl();
bool header_formatter(long packet_len, unsigned char *out, bool header_formatter(long packet_len, unsigned char *out,
const std::vector<tag_t> &tags); const std::vector<tag_t> &tags);
@@ -37,11 +37,11 @@ public:
std::vector<tag_t> &tags); std::vector<tag_t> &tags);
private: private:
int get_bit(int b, int i); int get_bit(int b, int i);
void generate_signal_field(char *out, tx_param &tx, ofdm_param &ofdm); void generate_signal_field(char *out, frame_param &frame, ofdm_param &ofdm);
}; };
} // namespace ieee802_11 } // namespace ieee802_11
} // namespace gr } // namespace gr
#endif /* INCLUDED_IEEE802_11_WIFI_SIGNAL_FIELD_IMPL_H */ #endif /* INCLUDED_IEEE802_11_SIGNAL_FIELD_IMPL_H */
+36 -35
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <ieee802-11/ofdm_sync_long.h> #include <ieee802-11/sync_long.h>
#include "utils.h" #include "utils.h"
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
#include <gnuradio/filter/fir_filter.h> #include <gnuradio/filter/fir_filter.h>
@@ -31,10 +31,10 @@ bool compare_abs(const std::pair<gr_complex, int>& first, const std::pair<gr_com
return abs(get<0>(first)) > abs(get<0>(second)); return abs(get<0>(first)) > abs(get<0>(second));
} }
class ofdm_sync_long_impl : public ofdm_sync_long { class sync_long_impl : public sync_long {
public: public:
ofdm_sync_long_impl(unsigned int sync_length, bool log, bool debug) : block("ofdm_sync_long", sync_long_impl(unsigned int sync_length, bool log, bool debug) : block("sync_long",
gr::io_signature::make2(2, 2, sizeof(gr_complex), sizeof(gr_complex)), gr::io_signature::make2(2, 2, sizeof(gr_complex), sizeof(gr_complex)),
gr::io_signature::make(1, 1, sizeof(gr_complex))), gr::io_signature::make(1, 1, sizeof(gr_complex))),
d_fir(gr::filter::kernel::fir_filter_ccc(1, LONG)), d_fir(gr::filter::kernel::fir_filter_ccc(1, LONG)),
@@ -48,7 +48,7 @@ ofdm_sync_long_impl(unsigned int sync_length, bool log, bool debug) : block("ofd
d_correlation = gr::fft::malloc_complex(8192); d_correlation = gr::fft::malloc_complex(8192);
} }
~ofdm_sync_long_impl(){ ~sync_long_impl(){
gr::fft::free(d_correlation); gr::fft::free(d_correlation);
} }
@@ -82,6 +82,7 @@ int general_work (int noutput, gr_vector_int& ninput_items,
if(d_state == COPY) { if(d_state == COPY) {
d_state = RESET; d_state = RESET;
} }
d_freq_offset_short = pmt::to_double(d_tags.front().value);
} }
} }
@@ -103,6 +104,7 @@ int general_work (int noutput, gr_vector_int& ninput_items,
if(d_offset == SYNC_LENGTH) { if(d_offset == SYNC_LENGTH) {
search_frame_start(); search_frame_start();
mylog(boost::format("LONG: frame start at %1%") % d_frame_start);
d_offset = 0; d_offset = 0;
d_count = 0; d_count = 0;
d_state = COPY; d_state = COPY;
@@ -120,9 +122,9 @@ int general_work (int noutput, gr_vector_int& ninput_items,
if(!rel) { if(!rel) {
add_item_tag(0, nitems_written(0), add_item_tag(0, nitems_written(0),
pmt::string_to_symbol("ofdm_start"), pmt::string_to_symbol("wifi_start"),
pmt::PMT_T, pmt::from_double(d_freq_offset_short - d_freq_offset),
pmt::string_to_symbol(name())); pmt::string_to_symbol(name()));
} }
if(rel >= 0 && (rel < 128 || ((rel - 128) % 80) > 15)) { if(rel >= 0 && (rel < 128 || ((rel - 128) % 80) > 15)) {
@@ -200,19 +202,17 @@ void search_frame_start() {
} }
int diff = abs(get<1>(vec[i]) - get<1>(vec[k])); int diff = abs(get<1>(vec[i]) - get<1>(vec[k]));
if(diff == 64) { if(diff == 64) {
d_frame_start = max(get<1>(vec[i]), get<1>(vec[k])) + 64 - 128 - 1; d_frame_start = min(get<1>(vec[i]), get<1>(vec[k]));
d_freq_offset = arg(first * conj(second)) / 64; d_freq_offset = arg(first * conj(second)) / 64;
//std::cout << "frequency offset " << d_freq_offset << std::endl;
// nice match found, return immediately // nice match found, return immediately
return; return;
// TODO: check if these offsets make sense
} else if(diff == 63) { } else if(diff == 63) {
d_frame_start = max(get<1>(vec[i]), get<1>(vec[k])) + 63 - 128 - 1; d_frame_start = min(get<1>(vec[i]), get<1>(vec[k]));
d_freq_offset = arg(first * conj(second)) / 64; d_freq_offset = arg(first * conj(second)) / 63;
} else if(diff == 65) { } else if(diff == 65) {
d_frame_start = max(get<1>(vec[i]), get<1>(vec[k])) + 64 - 128 - 1; d_frame_start = min(get<1>(vec[i]), get<1>(vec[k]));
d_freq_offset = arg(first * conj(second)) / 64; d_freq_offset = arg(first * conj(second)) / 65;
} }
} }
} }
@@ -224,6 +224,7 @@ private:
int d_offset; int d_offset;
int d_frame_start; int d_frame_start;
float d_freq_offset; float d_freq_offset;
double d_freq_offset_short;
gr_complex *d_correlation; gr_complex *d_correlation;
list<pair<gr_complex, int> > d_cor; list<pair<gr_complex, int> > d_cor;
@@ -237,28 +238,28 @@ private:
static const std::vector<gr_complex> LONG; static const std::vector<gr_complex> LONG;
}; };
ofdm_sync_long::sptr sync_long::sptr
ofdm_sync_long::make(unsigned int sync_length, bool log, bool debug) { sync_long::make(unsigned int sync_length, bool log, bool debug) {
return gnuradio::get_initial_sptr(new ofdm_sync_long_impl(sync_length, log, debug)); return gnuradio::get_initial_sptr(new sync_long_impl(sync_length, log, debug));
} }
const std::vector<gr_complex> ofdm_sync_long_impl::LONG = { const std::vector<gr_complex> sync_long_impl::LONG = {
gr_complex( 1.3868, 0.0000), gr_complex(-0.0455, -1.0679), gr_complex( 0.3528, -0.9865), gr_complex( 0.8594, 0.7348), gr_complex(-0.0455, -1.0679), gr_complex( 0.3528, -0.9865), gr_complex( 0.8594, 0.7348), gr_complex( 0.1874, 0.2475),
gr_complex( 0.1874, 0.2475), gr_complex( 0.5309, -0.7784), gr_complex(-1.0218, -0.4897), gr_complex(-0.3401, -0.9423), gr_complex( 0.5309, -0.7784), gr_complex(-1.0218, -0.4897), gr_complex(-0.3401, -0.9423), gr_complex( 0.8657, -0.2298),
gr_complex( 0.8657, -0.2298), gr_complex( 0.4734, 0.0362), gr_complex( 0.0088, -1.0207), gr_complex(-1.2142, -0.4205), gr_complex( 0.4734, 0.0362), gr_complex( 0.0088, -1.0207), gr_complex(-1.2142, -0.4205), gr_complex( 0.2172, -0.5195),
gr_complex( 0.2172, -0.5195), gr_complex( 0.5207, -0.1326), gr_complex(-0.1995, 1.4259), gr_complex( 1.0583, -0.0363), gr_complex( 0.5207, -0.1326), gr_complex(-0.1995, 1.4259), gr_complex( 1.0583, -0.0363), gr_complex( 0.5547, -0.5547),
gr_complex( 0.5547, -0.5547), gr_complex( 0.3277, 0.8728), gr_complex(-0.5077, 0.3488), gr_complex(-1.1650, 0.5789), gr_complex( 0.3277, 0.8728), gr_complex(-0.5077, 0.3488), gr_complex(-1.1650, 0.5789), gr_complex( 0.7297, 0.8197),
gr_complex( 0.7297, 0.8197), gr_complex( 0.6173, 0.1253), gr_complex(-0.5353, 0.7214), gr_complex(-0.5011, -0.1935), gr_complex( 0.6173, 0.1253), gr_complex(-0.5353, 0.7214), gr_complex(-0.5011, -0.1935), gr_complex(-0.3110, -1.3392),
gr_complex(-0.3110, -1.3392), gr_complex(-1.0818, -0.1470), gr_complex(-1.1300, -0.1820), gr_complex( 0.6663, -0.6571), gr_complex(-1.0818, -0.1470), gr_complex(-1.1300, -0.1820), gr_complex( 0.6663, -0.6571), gr_complex(-0.0249, 0.4773),
gr_complex(-0.0249, 0.4773), gr_complex(-0.8155, 1.0218), gr_complex( 0.8140, 0.9396), gr_complex( 0.1090, 0.8662), gr_complex(-0.8155, 1.0218), gr_complex( 0.8140, 0.9396), gr_complex( 0.1090, 0.8662), gr_complex(-1.3868, -0.0000),
gr_complex(-1.3868, 0.0000), gr_complex( 0.1090, -0.8662), gr_complex( 0.8140, -0.9396), gr_complex(-0.8155, -1.0218), gr_complex( 0.1090, -0.8662), gr_complex( 0.8140, -0.9396), gr_complex(-0.8155, -1.0218), gr_complex(-0.0249, -0.4773),
gr_complex(-0.0249, -0.4773), gr_complex( 0.6663, 0.6571), gr_complex(-1.1300, 0.1820), gr_complex(-1.0818, 0.1470), gr_complex( 0.6663, 0.6571), gr_complex(-1.1300, 0.1820), gr_complex(-1.0818, 0.1470), gr_complex(-0.3110, 1.3392),
gr_complex(-0.3110, 1.3392), gr_complex(-0.5011, 0.1935), gr_complex(-0.5353, -0.7214), gr_complex( 0.6173, -0.1253), gr_complex(-0.5011, 0.1935), gr_complex(-0.5353, -0.7214), gr_complex( 0.6173, -0.1253), gr_complex( 0.7297, -0.8197),
gr_complex( 0.7297, -0.8197), gr_complex(-1.1650, -0.5789), gr_complex(-0.5077, -0.3488), gr_complex( 0.3277, -0.8728), gr_complex(-1.1650, -0.5789), gr_complex(-0.5077, -0.3488), gr_complex( 0.3277, -0.8728), gr_complex( 0.5547, 0.5547),
gr_complex( 0.5547, 0.5547), gr_complex( 1.0583, 0.0363), gr_complex(-0.1995, -1.4259), gr_complex( 0.5207, 0.1326), gr_complex( 1.0583, 0.0363), gr_complex(-0.1995, -1.4259), gr_complex( 0.5207, 0.1326), gr_complex( 0.2172, 0.5195),
gr_complex( 0.2172, 0.5195), gr_complex(-1.2142, 0.4205), gr_complex( 0.0088, 1.0207), gr_complex( 0.4734, -0.0362), gr_complex(-1.2142, 0.4205), gr_complex( 0.0088, 1.0207), gr_complex( 0.4734, -0.0362), gr_complex( 0.8657, 0.2298),
gr_complex( 0.8657, 0.2298), gr_complex(-0.3401, 0.9423), gr_complex(-1.0218, 0.4897), gr_complex( 0.5309, 0.7784), gr_complex(-0.3401, 0.9423), gr_complex(-1.0218, 0.4897), gr_complex( 0.5309, 0.7784), gr_complex( 0.1874, -0.2475),
gr_complex( 0.1874, -0.2475), gr_complex( 0.8594, -0.7348), gr_complex( 0.3528, 0.9865), gr_complex(-0.0455, 1.0679) gr_complex( 0.8594, -0.7348), gr_complex( 0.3528, 0.9865), gr_complex(-0.0455, 1.0679), gr_complex( 1.3868, -0.0000),
}; };
+14 -14
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2013 Bastian Bloessl <bloessl@ccs-labs.org> * Copyright (C) 2013, 2016 Bastian Bloessl <bloessl@ccs-labs.org>
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <ieee802-11/ofdm_sync_short.h> #include <ieee802-11/sync_short.h>
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
#include "utils.h" #include "utils.h"
@@ -25,11 +25,11 @@ using namespace gr::ieee802_11;
static const int MIN_GAP = 480; static const int MIN_GAP = 480;
static const int MAX_SAMPLES = 540 * 80; static const int MAX_SAMPLES = 540 * 80;
class ofdm_sync_short_impl : public ofdm_sync_short { class sync_short_impl : public sync_short {
public: public:
ofdm_sync_short_impl(double threshold, unsigned int min_plateau, bool log, bool debug) : sync_short_impl(double threshold, unsigned int min_plateau, bool log, bool debug) :
block("ofdm_sync_short", block("sync_short",
gr::io_signature::make3(3, 3, sizeof(gr_complex), sizeof(gr_complex), sizeof(float)), gr::io_signature::make3(3, 3, sizeof(gr_complex), sizeof(gr_complex), sizeof(float)),
gr::io_signature::make(1, 1, sizeof(gr_complex))), gr::io_signature::make(1, 1, sizeof(gr_complex))),
d_log(log), d_log(log),
@@ -73,7 +73,7 @@ int general_work (int noutput_items, gr_vector_int& ninput_items,
d_copied = 0; d_copied = 0;
d_freq_offset = arg(in_abs[i]) / 16; d_freq_offset = arg(in_abs[i]) / 16;
d_plateau = 0; d_plateau = 0;
insert_tag(nitems_written(0)); insert_tag(nitems_written(0), d_freq_offset, nitems_read(0) + i);
dout << "SHORT Frame!" << std::endl; dout << "SHORT Frame!" << std::endl;
break; break;
} }
@@ -99,7 +99,7 @@ int general_work (int noutput_items, gr_vector_int& ninput_items,
d_copied = 0; d_copied = 0;
d_plateau = 0; d_plateau = 0;
d_freq_offset = arg(in_abs[o]) / 16; d_freq_offset = arg(in_abs[o]) / 16;
insert_tag(nitems_written(0) + o); insert_tag(nitems_written(0) + o, d_freq_offset, nitems_read(0) + o);
dout << "SHORT Frame!" << std::endl; dout << "SHORT Frame!" << std::endl;
break; break;
} }
@@ -128,11 +128,11 @@ int general_work (int noutput_items, gr_vector_int& ninput_items,
return 0; return 0;
} }
void insert_tag(uint64_t item) { void insert_tag(uint64_t item, double freq_offset, uint64_t input_item) {
mylog(boost::format("frame start at %1%") % item); mylog(boost::format("frame start at in: %2% out: %1%") % item % input_item);
const pmt::pmt_t key = pmt::string_to_symbol("ofdm_start"); const pmt::pmt_t key = pmt::string_to_symbol("wifi_start");
const pmt::pmt_t value = pmt::PMT_T; const pmt::pmt_t value = pmt::from_double(freq_offset);
const pmt::pmt_t srcid = pmt::string_to_symbol(name()); const pmt::pmt_t srcid = pmt::string_to_symbol(name());
add_item_tag(0, item, key, value, srcid); add_item_tag(0, item, key, value, srcid);
} }
@@ -148,7 +148,7 @@ private:
const unsigned int MIN_PLATEAU; const unsigned int MIN_PLATEAU;
}; };
ofdm_sync_short::sptr sync_short::sptr
ofdm_sync_short::make(double threshold, unsigned int min_plateau, bool log, bool debug) { sync_short::make(double threshold, unsigned int min_plateau, bool log, bool debug) {
return gnuradio::get_initial_sptr(new ofdm_sync_short_impl(threshold, min_plateau, log, debug)); return gnuradio::get_initial_sptr(new sync_short_impl(threshold, min_plateau, log, debug));
} }
+22 -105
View File
@@ -20,62 +20,6 @@
#include <cstring> #include <cstring>
#include <math.h> #include <math.h>
// constellations for different modulations (normalized to avg power 1)
const std::complex<double> BPSK_D[2] = {
std::complex<double>(-1.0, 0.0), std::complex<double>(1.0, 0.0)};
const std::complex<double> QPSK_D[4] = {
std::complex<double>(-0.7071, -0.7071), std::complex<double>(-0.7071, 0.7071),
std::complex<double>(+0.7071, -0.7071), std::complex<double>(+0.7071, 0.7071)};
const std::complex<double> QAM16_D[16] = {
std::complex<double>(-0.9487, -0.9487), std::complex<double>(-0.9487, -0.3162),
std::complex<double>(-0.9487, 0.9487), std::complex<double>(-0.9487, 0.3162),
std::complex<double>(-0.3162, -0.9487), std::complex<double>(-0.3162, -0.3162),
std::complex<double>(-0.3162, 0.9487), std::complex<double>(-0.3162, 0.3162),
std::complex<double>(0.9487, -0.9487), std::complex<double>(0.9487, -0.3162),
std::complex<double>(0.9487, 0.9487), std::complex<double>(0.9487, 0.3162),
std::complex<double>(0.3162, -0.9487), std::complex<double>(0.3162, -0.3162),
std::complex<double>(0.3162, 0.9487), std::complex<double>(0.3162, 0.3162)};
const std::complex<double> QAM64_D[64] = {
std::complex<double>(-1.0801, -1.0801), std::complex<double>(-1.0801, -0.7715),
std::complex<double>(-1.0801, -0.1543), std::complex<double>(-1.0801, -0.4629),
std::complex<double>(-1.0801, 1.0801), std::complex<double>(-1.0801, 0.7715),
std::complex<double>(-1.0801, 0.1543), std::complex<double>(-1.0801, 0.4629),
std::complex<double>(-0.7715, -1.0801), std::complex<double>(-0.7715, -0.7715),
std::complex<double>(-0.7715, -0.1543), std::complex<double>(-0.7715, -0.4629),
std::complex<double>(-0.7715, 1.0801), std::complex<double>(-0.7715, 0.7715),
std::complex<double>(-0.7715, 0.1543), std::complex<double>(-0.7715, 0.4629),
std::complex<double>(-0.1543, -1.0801), std::complex<double>(-0.1543, -0.7715),
std::complex<double>(-0.1543, -0.1543), std::complex<double>(-0.1543, -0.4629),
std::complex<double>(-0.1543, 1.0801), std::complex<double>(-0.1543, 0.7715),
std::complex<double>(-0.1543, 0.1543), std::complex<double>(-0.1543, 0.4629),
std::complex<double>(-0.4629, -1.0801), std::complex<double>(-0.4629, -0.7715),
std::complex<double>(-0.4629, -0.1543), std::complex<double>(-0.4629, -0.4629),
std::complex<double>(-0.4629, 1.0801), std::complex<double>(-0.4629, 0.7715),
std::complex<double>(-0.4629, 0.1543), std::complex<double>(-0.4629, 0.4629),
std::complex<double>(1.0801, -1.0801), std::complex<double>(1.0801, -0.7715),
std::complex<double>(1.0801, -0.1543), std::complex<double>(1.0801, -0.4629),
std::complex<double>(1.0801, 1.0801), std::complex<double>(1.0801, 0.7715),
std::complex<double>(1.0801, 0.1543), std::complex<double>(1.0801, 0.4629),
std::complex<double>(0.7715, -1.0801), std::complex<double>(0.7715, -0.7715),
std::complex<double>(0.7715, -0.1543), std::complex<double>(0.7715, -0.4629),
std::complex<double>(0.7715, 1.0801), std::complex<double>(0.7715, 0.7715),
std::complex<double>(0.7715, 0.1543), std::complex<double>(0.7715, 0.4629),
std::complex<double>(0.1543, -1.0801), std::complex<double>(0.1543, -0.7715),
std::complex<double>(0.1543, -0.1543), std::complex<double>(0.1543, -0.4629),
std::complex<double>(0.1543, 1.0801), std::complex<double>(0.1543, 0.7715),
std::complex<double>(0.1543, 0.1543), std::complex<double>(0.1543, 0.4629),
std::complex<double>(0.4629, -1.0801), std::complex<double>(0.4629, -0.7715),
std::complex<double>(0.4629, -0.1543), std::complex<double>(0.4629, -0.4629),
std::complex<double>(0.4629, 1.0801), std::complex<double>(0.4629, 0.7715),
std::complex<double>(0.4629, 0.1543), std::complex<double>(0.4629, 0.4629)};
ofdm_param::ofdm_param(Encoding e) { ofdm_param::ofdm_param(Encoding e) {
encoding = e; encoding = e;
@@ -153,37 +97,37 @@ ofdm_param::print() {
} }
tx_param::tx_param(ofdm_param &ofdm, int psdu_length) { frame_param::frame_param(ofdm_param &ofdm, int psdu_length) {
psdu_size = psdu_length; psdu_size = psdu_length;
// number of symbols (17-11) // number of symbols (17-11)
n_sym = (int) ceil((16 + 8 * psdu_size + 6) / (double) ofdm.n_dbps); n_sym = (int) ceil((16 + 8 * psdu_size + 6) / (double) ofdm.n_dbps);
// number of bits of the data field (17-12) n_data_bits = n_sym * ofdm.n_dbps;
n_data = n_sym * ofdm.n_dbps;
// number of padding bits (17-13) // number of padding bits (17-13)
n_pad = n_data - (16 + 8 * psdu_size + 6); n_pad = n_data_bits - (16 + 8 * psdu_size + 6);
n_encoded_bits = n_sym * ofdm.n_cbps; n_encoded_bits = n_sym * ofdm.n_cbps;
} }
void void
tx_param::print() { frame_param::print() {
std::cout << "TX Parameters:" << std::endl; std::cout << "FRAME Parameters:" << std::endl;
std::cout << "psdu_size: " << psdu_size << std::endl; std::cout << "psdu_size: " << psdu_size << std::endl;
std::cout << "n_sym: " << n_sym << std::endl; std::cout << "n_sym: " << n_sym << std::endl;
std::cout << "n_data: " << n_data << std::endl;
std::cout << "n_pad: " << n_pad << std::endl; std::cout << "n_pad: " << n_pad << std::endl;
std::cout << "n_encoded_bits: " << n_encoded_bits << std::endl;
std::cout << "n_data_bits: " << n_data_bits << std::endl;
} }
void scramble(const char *in, char *out, tx_param &tx, char initial_state) { void scramble(const char *in, char *out, frame_param &frame, char initial_state) {
int state = initial_state; int state = initial_state;
int feedback; int feedback;
for (int i = 0; i < tx.n_data; i++) { for (int i = 0; i < frame.n_data_bits; i++) {
feedback = (!!(state & 64)) ^ (!!(state & 8)); feedback = (!!(state & 64)) ^ (!!(state & 8));
out[i] = feedback ^ in[i]; out[i] = feedback ^ in[i];
@@ -192,8 +136,8 @@ void scramble(const char *in, char *out, tx_param &tx, char initial_state) {
} }
void reset_tail_bits(char *scrambled_data, tx_param &tx) { void reset_tail_bits(char *scrambled_data, frame_param &frame) {
memset(scrambled_data + tx.n_data - tx.n_pad - 6, 0, 6 * sizeof(char)); memset(scrambled_data + frame.n_data_bits - frame.n_pad - 6, 0, 6 * sizeof(char));
} }
@@ -208,11 +152,11 @@ int ones(int n) {
} }
void convolutional_encoding(const char *in, char *out, tx_param &tx) { void convolutional_encoding(const char *in, char *out, frame_param &frame) {
int state = 0; int state = 0;
for(int i = 0; i < tx.n_data; i++) { for(int i = 0; i < frame.n_data_bits; i++) {
assert(in[i] == 0 || in[i] == 1); assert(in[i] == 0 || in[i] == 1);
state = ((state << 1) & 0x7e) | in[i]; state = ((state << 1) & 0x7e) | in[i];
out[i * 2] = ones(state & 0155) % 2; out[i * 2] = ones(state & 0155) % 2;
@@ -221,11 +165,11 @@ void convolutional_encoding(const char *in, char *out, tx_param &tx) {
} }
void puncturing(const char *in, char *out, tx_param &tx, ofdm_param &ofdm) { void puncturing(const char *in, char *out, frame_param &frame, ofdm_param &ofdm) {
int mod; int mod;
for (int i = 0; i < tx.n_data * 2; i++) { for (int i = 0; i < frame.n_data_bits * 2; i++) {
switch(ofdm.encoding) { switch(ofdm.encoding) {
case BPSK_1_2: case BPSK_1_2:
case QPSK_1_2: case QPSK_1_2:
@@ -259,7 +203,7 @@ void puncturing(const char *in, char *out, tx_param &tx, ofdm_param &ofdm) {
} }
void interleave(const char *in, char *out, tx_param &tx, ofdm_param &ofdm, bool reverse) { void interleave(const char *in, char *out, frame_param &frame, ofdm_param &ofdm, bool reverse) {
int n_cbps = ofdm.n_cbps; int n_cbps = ofdm.n_cbps;
int first[n_cbps]; int first[n_cbps];
@@ -274,7 +218,7 @@ void interleave(const char *in, char *out, tx_param &tx, ofdm_param &ofdm, bool
second[i] = 16 * i - (n_cbps - 1) * int(floor(16.0 * i / n_cbps)); second[i] = 16 * i - (n_cbps - 1) * int(floor(16.0 * i / n_cbps));
} }
for(int i = 0; i < tx.n_sym; i++) { for(int i = 0; i < frame.n_sym; i++) {
for(int k = 0; k < n_cbps; k++) { for(int k = 0; k < n_cbps; k++) {
if(reverse) { if(reverse) {
out[i * n_cbps + second[first[k]]] = in[i * n_cbps + k]; out[i * n_cbps + second[first[k]]] = in[i * n_cbps + k];
@@ -286,55 +230,28 @@ void interleave(const char *in, char *out, tx_param &tx, ofdm_param &ofdm, bool
} }
void interleave(const double *in, double *out, tx_param &tx, ofdm_param &ofdm, bool reverse) { void split_symbols(const char *in, char *out, frame_param &frame, ofdm_param &ofdm) {
int n_cbps = ofdm.n_cbps; int symbols = frame.n_sym * 48;
int first[n_cbps];
int second[n_cbps];
int s = std::max(ofdm.n_bpsc / 2, 1);
for(int j = 0; j < n_cbps; j++) {
first[j] = s * (j / s) + ((j + int(floor(16.0 * j / n_cbps))) % s);
}
for(int i = 0; i < n_cbps; i++) {
second[i] = 16 * i - (n_cbps - 1) * int(floor(16.0 * i / n_cbps));
}
for(int i = 0; i < tx.n_sym; i++) {
for(int k = 0; k < n_cbps; k++) {
if(reverse) {
out[i * n_cbps + second[first[k]]] = in[i * n_cbps + k];
} else {
out[i * n_cbps + k] = in[i * n_cbps + second[first[k]]];
}
}
}
}
void split_symbols(const char *in, char *out, tx_param &tx, ofdm_param &ofdm) {
int symbols = tx.n_sym * 48;
for (int i = 0; i < symbols; i++) { for (int i = 0; i < symbols; i++) {
out[i] = 0; out[i] = 0;
for(int k = 0; k < ofdm.n_bpsc; k++) { for(int k = 0; k < ofdm.n_bpsc; k++) {
assert(*in == 1 || *in == 0); assert(*in == 1 || *in == 0);
out[i] |= (*in << (ofdm.n_bpsc - k - 1)); out[i] |= (*in << k);
in++; in++;
} }
} }
} }
void generate_bits(const char *psdu, char *data_bits, tx_param &tx) { void generate_bits(const char *psdu, char *data_bits, frame_param &frame) {
// first 16 bits are zero (SERVICE/DATA field) // first 16 bits are zero (SERVICE/DATA field)
memset(data_bits, 0, 16); memset(data_bits, 0, 16);
data_bits += 16; data_bits += 16;
for(int i = 0; i < tx.psdu_size; i++) { for(int i = 0; i < frame.psdu_size; i++) {
for(int b = 0; b < 8; b++) { for(int b = 0; b < 8; b++) {
data_bits[i * 8 + b] = !!(psdu[i] & (1 << b)); data_bits[i * 8 + b] = !!(psdu[i] & (1 << b));
} }
+22 -28
View File
@@ -14,32 +14,28 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef INCLUDED_IEEE802_11_OFDM_UTILS_H #ifndef INCLUDED_IEEE802_11_UTILS_H
#define INCLUDED_IEEE802_11_OFDM_UTILS_H #define INCLUDED_IEEE802_11_UTILS_H
#include <ieee802-11/api.h> #include <ieee802-11/api.h>
#include <ieee802-11/ofdm_mapper.h> #include <ieee802-11/mapper.h>
#include <gnuradio/config.h> #include <gnuradio/config.h>
#include <cinttypes> #include <cinttypes>
#include <iostream> #include <iostream>
const int MAX_SYM = 520; // enough for 1500 byte BPSK 1/2 #define MAX_PAYLOAD_SIZE 1500
const int MAX_BITS = 1550 * 8 * 2; #define MAX_PSDU_SIZE (MAX_PAYLOAD_SIZE + 28) // MAC, CRC
#define MAX_SYM (((16 + 8 * MAX_PSDU_SIZE + 6) / 24) + 1)
#define MAX_ENCODED_BITS ((16 + 8 * MAX_PSDU_SIZE + 6) * 2 + 288)
#define dout d_debug && std::cout #define dout d_debug && std::cout
#if defined(HAVE_LOG4CPP) && defined(ENABLE_GR_LOG) #if defined(HAVE_LOG4CPP) && defined(ENABLE_GR_LOG) && defined(GR_IEEE80211_LOG4CPP)
#define mylog(msg) do { if(d_log) { *d_logger << log4cpp::Priority::INFO << msg << log4cpp::eol; }} while(0); #define mylog(msg) do { if(d_log) { GR_LOG_INFO(d_logger, msg); }} while(0);
#else #else
#define mylog(msg) do { d_log && std::cout << msg << std::endl; } while(0); #define mylog(msg) do { d_log && std::cout << msg << std::endl; } while(0);
#endif #endif
// same mappings in double (itpp sucks)
extern const std::complex<double> BPSK_D[2];
extern const std::complex<double> QPSK_D[4];
extern const std::complex<double> QAM16_D[16];
extern const std::complex<double> QAM64_D[64];
struct mac_header { struct mac_header {
//protocol version, type, subtype, to_ds, from_ds, ... //protocol version, type, subtype, to_ds, from_ds, ...
uint16_t frame_control; uint16_t frame_control;
@@ -51,7 +47,7 @@ struct mac_header {
}__attribute__((packed)); }__attribute__((packed));
/** /**
* OFDM parameters * WIFI parameters
*/ */
class ofdm_param { class ofdm_param {
public: public:
@@ -74,18 +70,18 @@ public:
/** /**
* packet specific parameters * packet specific parameters
*/ */
class tx_param { class frame_param {
public: public:
tx_param(ofdm_param &ofdm, int psdu_length); frame_param(ofdm_param &ofdm, int psdu_length);
// PSDU size in bytes // PSDU size in bytes
int psdu_size; int psdu_size;
// number of OFDM symbols (17-11) // number of OFDM symbols (17-11)
int n_sym; int n_sym;
// number of data bits in the DATA field, including service and padding (17-12)
int n_data;
// number of padding bits in the DATA field (17-13) // number of padding bits in the DATA field (17-13)
int n_pad; int n_pad;
int n_encoded_bits; int n_encoded_bits;
// number of data bits, including service and padding (17-12)
int n_data_bits;
void print(); void print();
}; };
@@ -104,20 +100,18 @@ public:
*/ */
void generate_mac_data_frame(const char *msdu, int msdu_size, char **psdu, int *psdu_size, char seq); void generate_mac_data_frame(const char *msdu, int msdu_size, char **psdu, int *psdu_size, char seq);
void scramble(const char *input, char *out, frame_param &frame, char initial_state);
void scramble(const char *input, char *out, tx_param &tx, char initial_state); void reset_tail_bits(char *scrambled_data, frame_param &frame);
void reset_tail_bits(char *scrambled_data, tx_param &tx); void convolutional_encoding(const char *input, char *out, frame_param &frame);
void convolutional_encoding(const char *input, char *out, tx_param &tx); void puncturing(const char *input, char *out, frame_param &frame, ofdm_param &ofdm);
void puncturing(const char *input, char *out, tx_param &tx, ofdm_param &ofdm); void interleave(const char *input, char *out, frame_param &frame, ofdm_param &ofdm, bool reverse = false);
void interleave(const char *input, char *out, tx_param &tx, ofdm_param &ofdm, bool reverse = false); void split_symbols(const char *input, char *out, frame_param &frame, ofdm_param &ofdm);
void interleave(const double *input, double *out, tx_param &tx, ofdm_param &ofdm, bool reverse = false);
void split_symbols(const char *input, char *out, tx_param &tx, ofdm_param &ofdm); void generate_bits(const char *psdu, char *data_bits, frame_param &frame);
void generate_bits(const char *psdu, char *data_bits, tx_param &tx); #endif /* INCLUDED_IEEE802_11_UTILS_H */
#endif /* INCLUDED_IEEE802_11_OFDM_UTILS_H */
+419
View File
@@ -0,0 +1,419 @@
/*
* Copyright 1995 Phil Karn, KA9Q
* Copyright 2008 Free Software Foundation, Inc.
* 2014 Added SSE2 implementation Bogdan Diaconescu
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
/*
* Viterbi decoder for K=7 rate=1/2 convolutional code
* Some modifications from original Karn code by Matt Ettus
* Major modifications by adding SSE2 code by Bogdan Diaconescu
*/
#include "viterbi_decoder.h"
#include <cstring>
#include <iostream>
/* The basic Viterbi decoder operation, called a "butterfly"
* operation because of the way it looks on a trellis diagram. Each
* butterfly involves an Add-Compare-Select (ACS) operation on the two nodes
* where the 0 and 1 paths from the current node merge at the next step of
* the trellis.
*
* The code polynomials are assumed to have 1's on both ends. Given a
* function encode_state() that returns the two symbols for a given
* encoder state in the low two bits, such a code will have the following
* identities for even 'n' < 64:
*
* encode_state(n) = encode_state(n+65)
* encode_state(n+1) = encode_state(n+64) = (3 ^ encode_state(n))
*
* Any convolutional code you would actually want to use will have
* these properties, so these assumptions aren't too limiting.
*
* Doing this as a macro lets the compiler evaluate at compile time the
* many expressions that depend on the loop index and encoder state and
* emit them as immediate arguments.
* This makes an enormous difference on register-starved machines such
* as the Intel x86 family where evaluating these expressions at runtime
* would spill over into memory.
*/
#define BUTTERFLY(i,sym) { \
int m0,m1,m2,m3; \
/* ACS for 0 branch */ \
m0 = state[i].metric + mets[sym]; /* 2*i */ \
m1 = state[i+32].metric + mets[3 ^ sym]; /* 2*i + 64 */ \
if(m0 > m1){ \
next[2*i].metric = m0; \
next[2*i].path = state[i].path << 1; \
} else { \
next[2*i].metric = m1; \
next[2*i].path = (state[i+32].path << 1)|1; \
} \
/* ACS for 1 branch */ \
m2 = state[i].metric + mets[3 ^ sym]; /* 2*i + 1 */ \
m3 = state[i+32].metric + mets[sym]; /* 2*i + 65 */ \
if(m2 > m3){ \
next[2*i+1].metric = m2; \
next[2*i+1].path = state[i].path << 1; \
} else { \
next[2*i+1].metric = m3; \
next[2*i+1].path = (state[i+32].path << 1)|1; \
} \
}
using namespace gr::ieee802_11;
viterbi_decoder::viterbi_decoder() :
d_store_pos(0) {
}
viterbi_decoder::~viterbi_decoder() {
}
void
viterbi_decoder::viterbi_butterfly2_sse2(unsigned char *symbols,
__m128i *mm0, __m128i *mm1, __m128i *pp0, __m128i *pp1) {
int i;
__m128i *metric0, *metric1;
__m128i *path0, *path1;
metric0 = mm0;
path0 = pp0;
metric1 = mm1;
path1 = pp1;
// Operate on 4 symbols (2 bits) at a time
__m128i m0, m1, m2, m3, decision0, decision1, survivor0, survivor1;
__m128i metsv, metsvm;
__m128i shift0, shift1;
__m128i tmp0, tmp1;
__m128i sym0v, sym1v;
sym0v = _mm_set1_epi8(symbols[0]);
sym1v = _mm_set1_epi8(symbols[1]);
for (i = 0; i < 2; i++) {
if (symbols[0] == 2) {
metsvm = _mm_xor_si128(d_branchtab27_sse2[1].v[i],sym1v);
metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm);
} else if (symbols[1] == 2) {
metsvm = _mm_xor_si128(d_branchtab27_sse2[0].v[i],sym0v);
metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm);
} else {
metsvm = _mm_add_epi8(_mm_xor_si128(d_branchtab27_sse2[0].v[i],sym0v),_mm_xor_si128(d_branchtab27_sse2[1].v[i],sym1v));
metsv = _mm_sub_epi8(_mm_set1_epi8(2),metsvm);
}
m0 = _mm_add_epi8(metric0[i], metsv);
m1 = _mm_add_epi8(metric0[i+2], metsvm);
m2 = _mm_add_epi8(metric0[i], metsvm);
m3 = _mm_add_epi8(metric0[i+2], metsv);
decision0 = _mm_cmpgt_epi8(_mm_sub_epi8(m0,m1),_mm_setzero_si128());
decision1 = _mm_cmpgt_epi8(_mm_sub_epi8(m2,m3),_mm_setzero_si128());
survivor0 = _mm_or_si128(_mm_and_si128(decision0,m0),_mm_andnot_si128(decision0,m1));
survivor1 = _mm_or_si128(_mm_and_si128(decision1,m2),_mm_andnot_si128(decision1,m3));
shift0 = _mm_slli_epi16(path0[i], 1);
shift1 = _mm_slli_epi16(path0[2+i], 1);
shift1 = _mm_add_epi8(shift1, _mm_set1_epi8(1));
metric1[2*i] = _mm_unpacklo_epi8(survivor0,survivor1);
tmp0 = _mm_or_si128(_mm_and_si128(decision0,shift0),_mm_andnot_si128(decision0,shift1));
metric1[2*i+1] = _mm_unpackhi_epi8(survivor0,survivor1);
tmp1 = _mm_or_si128(_mm_and_si128(decision1,shift0),_mm_andnot_si128(decision1,shift1));
path1[2*i] = _mm_unpacklo_epi8(tmp0, tmp1);
path1[2*i+1] = _mm_unpackhi_epi8(tmp0, tmp1);
}
metric0 = mm1;
path0 = pp1;
metric1 = mm0;
path1 = pp0;
sym0v = _mm_set1_epi8(symbols[2]);
sym1v = _mm_set1_epi8(symbols[3]);
for (i = 0; i < 2; i++) {
if (symbols[2] == 2) {
metsvm = _mm_xor_si128(d_branchtab27_sse2[1].v[i],sym1v);
metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm);
} else if (symbols[3] == 2) {
metsvm = _mm_xor_si128(d_branchtab27_sse2[0].v[i],sym0v);
metsv = _mm_sub_epi8(_mm_set1_epi8(1),metsvm);
} else {
metsvm = _mm_add_epi8(_mm_xor_si128(d_branchtab27_sse2[0].v[i],sym0v),_mm_xor_si128(d_branchtab27_sse2[1].v[i],sym1v));
metsv = _mm_sub_epi8(_mm_set1_epi8(2),metsvm);
}
m0 = _mm_add_epi8(metric0[i], metsv);
m1 = _mm_add_epi8(metric0[i+2], metsvm);
m2 = _mm_add_epi8(metric0[i], metsvm);
m3 = _mm_add_epi8(metric0[i+2], metsv);
decision0 = _mm_cmpgt_epi8(_mm_sub_epi8(m0,m1),_mm_setzero_si128());
decision1 = _mm_cmpgt_epi8(_mm_sub_epi8(m2,m3),_mm_setzero_si128());
survivor0 = _mm_or_si128(_mm_and_si128(decision0,m0),_mm_andnot_si128(decision0,m1));
survivor1 = _mm_or_si128(_mm_and_si128(decision1,m2),_mm_andnot_si128(decision1,m3));
shift0 = _mm_slli_epi16(path0[i], 1);
shift1 = _mm_slli_epi16(path0[2+i], 1);
shift1 = _mm_add_epi8(shift1, _mm_set1_epi8(1));
metric1[2*i] = _mm_unpacklo_epi8(survivor0,survivor1);
tmp0 = _mm_or_si128(_mm_and_si128(decision0,shift0),_mm_andnot_si128(decision0,shift1));
metric1[2*i+1] = _mm_unpackhi_epi8(survivor0,survivor1);
tmp1 = _mm_or_si128(_mm_and_si128(decision1,shift0),_mm_andnot_si128(decision1,shift1));
path1[2*i] = _mm_unpacklo_epi8(tmp0, tmp1);
path1[2*i+1] = _mm_unpackhi_epi8(tmp0, tmp1);
}
}
// Find current best path
unsigned char
viterbi_decoder::viterbi_get_output_sse2(__m128i *mm0, __m128i *pp0,
int ntraceback, unsigned char *outbuf) {
int i;
int bestmetric, minmetric;
int beststate = 0;
int pos = 0;
// circular buffer with the last ntraceback paths
d_store_pos = (d_store_pos + 1) % ntraceback;
for (i = 0; i < 4; i++) {
_mm_store_si128((__m128i *) &d_mmresult[i*16], mm0[i]);
_mm_store_si128((__m128i *) &d_ppresult[d_store_pos][i*16], pp0[i]);
}
// Find out the best final state
bestmetric = d_mmresult[beststate];
minmetric = d_mmresult[beststate];
for (i = 1; i < 64; i++) {
if (d_mmresult[i] > bestmetric) {
bestmetric = d_mmresult[i];
beststate = i;
}
if (d_mmresult[i] < minmetric) {
minmetric = d_mmresult[i];
}
}
// Trace back
for (i = 0, pos = d_store_pos; i < (ntraceback - 1); i++) {
// Obtain the state from the output bits
// by clocking in the output bits in reverse order.
// The state has only 6 bits
beststate = d_ppresult[pos][beststate] >> 2;
pos = (pos - 1 + ntraceback) % ntraceback;
}
// Store output byte
*outbuf = d_ppresult[pos][beststate];
// Zero out the path variable
// and prevent metric overflow
for (i = 0; i < 4; i++) {
pp0[i] = _mm_setzero_si128();
mm0[i] = _mm_sub_epi8(mm0[i], _mm_set1_epi8(minmetric));
}
return bestmetric;
}
uint8_t*
viterbi_decoder::depuncture(uint8_t *in) {
int count;
int n_cbps = d_ofdm->n_cbps;
uint8_t *depunctured;
if (d_ntraceback == 5) {
count = d_frame->n_sym * n_cbps;
depunctured = in;
} else {
depunctured = d_depunctured;
count = 0;
for(int i = 0; i < d_frame->n_sym; i++) {
for(int k = 0; k < n_cbps; k++) {
while (d_depuncture_pattern[count % (2 * d_k)] == 0) {
depunctured[count] = 2;
count++;
}
// Insert received bits
depunctured[count] = in[i * n_cbps + k];
count++;
while (d_depuncture_pattern[count % (2 * d_k)] == 0) {
depunctured[count] = 2;
count++;
}
}
}
}
return depunctured;
}
uint8_t*
viterbi_decoder::decode(ofdm_param *ofdm, frame_param *frame, uint8_t *in) {
d_ofdm = ofdm;
d_frame = frame;
reset();
uint8_t *depunctured = depuncture(in);
int in_count = 0;
int out_count = 0;
int n_decoded = 0;
while(n_decoded < d_frame->n_data_bits) {
if ((in_count % 4) == 0) { //0 or 3
viterbi_butterfly2_sse2(&depunctured[in_count & 0xfffffffc], d_metric0, d_metric1, d_path0, d_path1);
if ((in_count > 0) && (in_count % 16) == 8) { // 8 or 11
unsigned char c;
viterbi_get_output_sse2(d_metric0, d_path0, d_ntraceback, &c);
if (out_count >= d_ntraceback) {
for (int i= 0; i < 8; i++) {
d_decoded[(out_count - d_ntraceback) * 8 + i] = (c >> (7 - i)) & 0x1;
n_decoded++;
}
}
out_count++;
}
}
in_count++;
}
return d_decoded;
}
void
viterbi_decoder::reset() {
viterbi_chunks_init_sse2();
switch(d_ofdm->encoding) {
case BPSK_1_2:
case QPSK_1_2:
case QAM16_1_2:
d_ntraceback = 5;
d_depuncture_pattern = PUNCTURE_1_2;
d_k = 1;
break;
case QAM64_2_3:
d_ntraceback = 9;
d_depuncture_pattern = PUNCTURE_2_3;
d_k = 2;
break;
case BPSK_3_4:
case QPSK_3_4:
case QAM16_3_4:
case QAM64_3_4:
d_ntraceback = 10;
d_depuncture_pattern = PUNCTURE_3_4;
d_k = 3;
break;
}
}
void // Initialize starting metrics to prefer 0 state
viterbi_decoder::viterbi_chunks_init_sse2() {
int i, j;
for (i = 0; i < 4; i++) {
d_metric0[i] = _mm_setzero_si128();
d_path0[i] = _mm_setzero_si128();
}
int polys[2] = { 0x6d, 0x4f };
for(i=0; i < 32; i++) {
d_branchtab27_sse2[0].c[i] = (polys[0] < 0) ^ PARTAB[(2*i) & abs(polys[0])] ? 1 : 0;
d_branchtab27_sse2[1].c[i] = (polys[1] < 0) ^ PARTAB[(2*i) & abs(polys[1])] ? 1 : 0;
}
for (i = 0; i < 64; i++) {
d_mmresult[i] = 0;
for (j = 0; j < TRACEBACK_MAX; j++) {
d_ppresult[j][i] = 0;
}
}
}
/* Parity lookup table */
const unsigned char viterbi_decoder::PARTAB[256] = {
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0,
};
const unsigned char viterbi_decoder::PUNCTURE_1_2[2] = {1, 1};
const unsigned char viterbi_decoder::PUNCTURE_2_3[4] = {1, 1, 1, 0};
const unsigned char viterbi_decoder::PUNCTURE_3_4[6] = {1, 1, 1, 0, 0, 1};
+89
View File
@@ -0,0 +1,89 @@
/*
* Copyright (C) 2016 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_IEEE802_11_VITERBI_DECODER_H
#define INCLUDED_IEEE802_11_VITERBI_DECODER_H
#include <xmmintrin.h>
#include "utils.h"
namespace gr {
namespace ieee802_11 {
// Maximum number of traceback bytes
#define TRACEBACK_MAX 24
/* This Viterbi decoder was taken from the gr-dvbt module of
* GNU Radio. It is an SSE2 version of the Viterbi Decoder
* created by Phil Karn. The SSE2 version was made by Bogdan
* Diaconescu. For more info see: gr-dvbt/lib/d_viterbi.h
*/
class viterbi_decoder
{
public:
viterbi_decoder();
virtual ~viterbi_decoder();
uint8_t* decode(ofdm_param *ofdm, frame_param *frame, uint8_t *in);
private:
// Position in circular buffer where the current decoded byte is stored
int d_store_pos;
// Metrics for each state
unsigned char d_mmresult[64] __attribute__((aligned(16)));
// Paths for each state
unsigned char d_ppresult[TRACEBACK_MAX][64] __attribute__((aligned(16)));
union branchtab27 {
unsigned char c[32];
__m128i v[2];
} d_branchtab27_sse2[2];
__m128i d_metric0[4] __attribute__ ((aligned(16)));
__m128i d_metric1[4] __attribute__ ((aligned(16)));
__m128i d_path0[4] __attribute__ ((aligned(16)));
__m128i d_path1[4] __attribute__ ((aligned(16)));
int d_ntraceback;
int d_k;
ofdm_param *d_ofdm;
frame_param *d_frame;
const unsigned char *d_depuncture_pattern;
uint8_t d_depunctured[MAX_ENCODED_BITS];
uint8_t d_decoded[MAX_ENCODED_BITS * 3 / 4];
static const unsigned char PARTAB[256];
static const unsigned char PUNCTURE_1_2[2];
static const unsigned char PUNCTURE_2_3[4];
static const unsigned char PUNCTURE_3_4[6];
void reset();
uint8_t* depuncture(uint8_t *in);
void viterbi_chunks_init_sse2();
void viterbi_butterfly2_sse2(unsigned char *symbols,
__m128i m0[], __m128i m1[], __m128i p0[], __m128i p1[]);
unsigned char viterbi_get_output_sse2(__m128i *mm0,
__m128i *pp0, int ntraceback, unsigned char *outbuf);
};
} // namespace ieee802_11
} // namespace gr
#endif /* INCLUDED_IEEE802_11_VITERBI_DECODER_H */
-106
View File
@@ -1,106 +0,0 @@
/*
* Copyright (C) 2014 Bastian Bloessl <bloessl@ccs-labs.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ieee802-11/wifi_edca.h>
#include <gnuradio/io_signature.h>
#include <gnuradio/block_detail.h>
#include "utils.h"
#include <boost/crc.hpp>
#include <iostream>
#include <stdexcept>
using namespace gr::ieee802_11;
class wifi_edca_impl : public wifi_edca {
public:
wifi_edca_impl(std::vector<uint16_t> cw_min, std::vector<uint16_t>aifsn) :
block("wifi_edca",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0)),
m_cw_min(cw_min), m_aifsn(aifsn)
{
if(cw_min.size() != aifsn.size()) {
throw std::invalid_argument("WiFi EDCA: cw_min and aifsn parameters have to have same length");
}
if(cw_min.size() == 0) {
throw std::invalid_argument("WiFi EDCA need cw_min and aifsn");
}
message_port_register_out(pmt::mp("mac out"));
if(cw_min.size() == 1) {
message_port_register_in(pmt::mp("ac_in"));
set_msg_handler(pmt::mp("ac_in"), boost::bind(&wifi_edca_impl::ac_in, this, _1, 0));
} else {
for(int i = 0; i < cw_min.size(); i++) {
std::stringstream sstm;
sstm << "ac in" << i;
message_port_register_in(pmt::mp(sstm.str()));
set_msg_handler(pmt::mp(sstm.str()), boost::bind(&wifi_edca_impl::ac_in, this, _1, i));
}
}
}
void ac_in (pmt::pmt_t msg, int i) {
std::cout << "ac " << i << std::endl;
if(pmt::is_eof_object(msg)) {
message_port_pub(pmt::mp("mac out"), pmt::PMT_EOF);
detail().get()->set_done(true);
} else if(pmt::is_symbol(msg)) {
std::string str;
str = pmt::symbol_to_string(msg);
pmt::pmt_t dict = pmt::make_dict();
dict = pmt::dict_add(dict, pmt::mp("cw_min"), pmt::from_long(m_cw_min[i]));
dict = pmt::dict_add(dict, pmt::mp("aifsn"), pmt::from_long(m_aifsn[i]));
pmt::pmt_t blob = pmt::make_blob(str.data(), str.length());
pmt::pmt_t pair = pmt::cons(dict, blob);
message_port_pub(pmt::mp("mac out"), pair);
} else if(pmt::is_pair(msg)) {
pmt::pmt_t dict = pmt::car(msg);
dict = pmt::dict_add(dict, pmt::mp("cw_min"), pmt::from_long(m_cw_min[i]));
dict = pmt::dict_add(dict, pmt::mp("aifsn"), pmt::from_long(m_aifsn[i]));
message_port_pub(pmt::mp("mac out"), pmt::cons(dict, pmt::cdr(msg)));
} else {
throw std::invalid_argument("WiFi EDCA expects PDUs or strings");
}
}
private:
std::vector<uint16_t>m_cw_min;
std::vector<uint16_t>m_aifsn;
};
wifi_edca::sptr
wifi_edca::make(std::vector<uint16_t>cw_min, std::vector<uint16_t> aifsn) {
return gnuradio::get_initial_sptr(new wifi_edca_impl(cw_min, aifsn));
}
-1
View File
@@ -39,4 +39,3 @@ include(GrTest)
set(GR_TEST_TARGET_DEPS gnuradio-ieee802-11) set(GR_TEST_TARGET_DEPS gnuradio-ieee802-11)
set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig) set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig)
#GR_ADD_TEST(qa_howto ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_howto.py)
+2
View File
@@ -0,0 +1,2 @@
results/
sim.py
+30
View File
@@ -0,0 +1,30 @@
SHELL=/bin/bash
MESSAGES=100
PCAPFILES=$(shell python -c 'import itertools; import numpy as np; print(" ".join(["results/sim_%d_%d_%.1f_.pcap" % x for x in itertools.product(range(10), range(8), np.arange(0, 30,.5))]))')
all: pdr.pdf
pdr.pdf: plot.py results/all.csv
python ./plot.py
sim.py: sim.grc
grcc -d . sim.grc
results/all.csv: $(PCAPFILES)
./parse.sh
%.pcap: sim.py
@echo $@
mkdir -p results
export GR_CONF_DEFAULT_MAX_MESSAGES=123
$(eval REPETITION=$(shell python -c "print \"$@\".split(\"_\")[1]"))
$(eval ENCODING=$(shell python -c "print \"$@\".split(\"_\")[2]"))
$(eval SNR=$(shell python -c "print \"$@\".split(\"_\")[3]"))
@echo REPETITION=$(REPETITION)
@echo ENCODING=$(ENCODING)
@echo SNR=$(SNR)
./sim.py --messages=$(MESSAGES) --encoding=$(ENCODING) --snr=$(SNR) --repetition=$(REPETITION)
#gdb -ex run -ex quit --args python ./sim.py --messages=$(MESSAGES) --encoding=$(ENCODING) --snr=$(SNR) --repetition=$(REPETITION)
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
files=`ls results/*.pcap`
outfile=results/all.csv
rm -f ${outfile}
echo "repetition;encoding;snr;received"
echo "repetition;encoding;snr;received" > ${outfile}
for f in ${files}
do
repetition=`python -c "print \"${f}\".split(\"_\")[1]"`
encoding=`python -c "print \"${f}\".split(\"_\")[2]"`
snr=`python -c "print \"${f}\".split(\"_\")[3]"`
echo "file ${f} repetition ${repetition} encoding ${encoding} snr ${snr}"
rcvd=`tshark -r ${f} | wc -l | tr -d " "`
echo "${repetition};${encoding};${snr};${rcvd}"
echo "${repetition};${encoding};${snr};${rcvd}" >> ${outfile}
done
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
pdr = pd.read_csv('./results/all.csv', sep=';')
pdr['encoding'] = pdr.encoding.astype("category", categories=range(8), ordered=True)
pdr.encoding.cat.categories = [
"BPSK 1/2", "BPSK 3/4",
"QPSK 1/2", "QPSK 3/4",
"16-QAM 1/2", "16-QAM 3/4",
"64-QAM 2/3", "64-QAM 3/4"]
a = pdr.groupby(['encoding', 'snr'])
b = a.agg({'received': np.mean}).reset_index()
c = b.pivot(index='snr', columns='encoding', values='received')
c.plot()
plt.savefig('pdr.pdf')
+957
View File
@@ -0,0 +1,957 @@
<?xml version='1.0' encoding='utf-8'?>
<?grc format='1' created='3.8.git'?>
<flow_graph>
<timestamp>Sat Feb 1 18:28:19 2014</timestamp>
<block>
<key>options</key>
<param>
<key>author</key>
<value></value>
</param>
<param>
<key>window_size</key>
<value>1280, 1024</value>
</param>
<param>
<key>category</key>
<value>Custom</value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>description</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 13)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>generate_options</key>
<value>no_gui</value>
</param>
<param>
<key>hier_block_src_path</key>
<value>.:</value>
</param>
<param>
<key>id</key>
<value>sim</value>
</param>
<param>
<key>max_nouts</key>
<value>0</value>
</param>
<param>
<key>qt_qss_theme</key>
<value></value>
</param>
<param>
<key>realtime_scheduling</key>
<value></value>
</param>
<param>
<key>run_command</key>
<value>{python} -u {filename}</value>
</param>
<param>
<key>run_options</key>
<value>run</value>
</param>
<param>
<key>run</key>
<value>True</value>
</param>
<param>
<key>thread_safe_setters</key>
<value></value>
</param>
<param>
<key>title</key>
<value></value>
</param>
</block>
<block>
<key>variable</key>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 260)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>filename</value>
</param>
<param>
<key>value</key>
<value> "results/sim_%d_%d_%.1f_.pcap" % (repetition, encoding, snr)</value>
</param>
</block>
<block>
<key>variable</key>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 93)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>out_buf_size</value>
</param>
<param>
<key>value</key>
<value>96000</value>
</param>
</block>
<block>
<key>analog_noise_source_x</key>
<param>
<key>amp</key>
<value>1</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(916, 616)</value>
</param>
<param>
<key>_rotation</key>
<value>90</value>
</param>
<param>
<key>id</key>
<value>analog_noise_source_x_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>noise_type</key>
<value>analog.GR_GAUSSIAN</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>seed</key>
<value>repetition</value>
</param>
</block>
<block>
<key>blocks_add_xx</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(904, 496)</value>
</param>
<param>
<key>_rotation</key>
<value>90</value>
</param>
<param>
<key>id</key>
<value>blocks_add_xx_0</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>num_inputs</key>
<value>2</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
</block>
<block>
<key>blocks_file_sink</key>
<param>
<key>append</key>
<value>False</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>file</key>
<value>filename</value>
</param>
<param>
<key>_coordinate</key>
<value>(256, 388)</value>
</param>
<param>
<key>_rotation</key>
<value>180</value>
</param>
<param>
<key>id</key>
<value>blocks_file_sink_0_0</value>
</param>
<param>
<key>type</key>
<value>byte</value>
</param>
<param>
<key>unbuffered</key>
<value>False</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
</block>
<block>
<key>blocks_multiply_const_vxx</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>const</key>
<value>(10**(snr/10.0))**.5</value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(688, 588)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>blocks_multiply_const_vxx_0</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value>0, 1, ..., 6, 7
corresponds to BPSK 1/2, ..., 64-QAM 3/4</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(792, 11)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>encoding</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>e</value>
</param>
<param>
<key>type</key>
<value>intx</value>
</param>
<param>
<key>value</key>
<value>0</value>
</param>
</block>
<block>
<key>foo_packet_pad2</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>debug</key>
<value>False</value>
</param>
<param>
<key>delay_sec</key>
<value>0.001</value>
</param>
<param>
<key>delay</key>
<value>False</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(512, 560)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>foo_packet_pad2_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>out_buf_size</value>
</param>
<param>
<key>pad_front</key>
<value>1000</value>
</param>
<param>
<key>pad_tail</key>
<value>1000</value>
</param>
</block>
<block>
<key>foo_random_periodic_msg_source</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>debug</key>
<value>False</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(392, 200)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>foo_random_periodic_msg_source_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>msg_len</key>
<value>pdu_len - 24</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>num</key>
<value>messages</value>
</param>
<param>
<key>interval</key>
<value>5</value>
</param>
<param>
<key>quit</key>
<value>True</value>
</param>
<param>
<key>seed</key>
<value>repetition</value>
</param>
</block>
<block>
<key>foo_wireshark_connector</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>debug</key>
<value>False</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(464, 396)</value>
</param>
<param>
<key>_rotation</key>
<value>180</value>
</param>
<param>
<key>id</key>
<value>foo_wireshark_connector_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>tech</key>
<value>127</value>
</param>
</block>
<block>
<key>ieee802_11_mac</key>
<param>
<key>bss_mac</key>
<value>[0xff, 0xff, 0xff, 0xff, 0xff, 0xff]</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>dst_mac</key>
<value>[0x42, 0x42, 0x42, 0x42, 0x42, 0x42]</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(720, 236)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>ieee802_11_mac_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>src_mac</key>
<value>[0x23, 0x23, 0x23, 0x23, 0x23, 0x23]</value>
</param>
</block>
<block>
<key>import</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 156)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>import_0</value>
</param>
<param>
<key>import</key>
<value>import math</value>
</param>
</block>
<block>
<key>import</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 212)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>import_1</value>
</param>
<param>
<key>import</key>
<value>import random</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value>Number of messages to generate</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(416, 6)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>messages</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>n</value>
</param>
<param>
<key>type</key>
<value>intx</value>
</param>
<param>
<key>value</key>
<value>10</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value>Packet size (in byte)</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(1048, 11)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>pdu_len</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>l</value>
</param>
<param>
<key>type</key>
<value>intx</value>
</param>
<param>
<key>value</key>
<value>435</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value>Current repetition of experiment.</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(208, 11)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>repetition</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>r</value>
</param>
<param>
<key>type</key>
<value>intx</value>
</param>
<param>
<key>value</key>
<value>23</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value>Signal to Noise Ratio</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(632, 6)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>snr</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>s</value>
</param>
<param>
<key>type</key>
<value>eng_float</value>
</param>
<param>
<key>value</key>
<value>10</value>
</param>
</block>
<block>
<key>wifi_phy_hier</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(720, 408)</value>
</param>
<param>
<key>_rotation</key>
<value>180</value>
</param>
<param>
<key>id</key>
<value>wifi_phy_hier_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>bandwidth</key>
<value>10e6</value>
</param>
<param>
<key>chan_est</key>
<value>ieee802_11.LS</value>
</param>
<param>
<key>encoding</key>
<value>encoding</value>
</param>
<param>
<key>frequency</key>
<value>5.89e9</value>
</param>
<param>
<key>sensitivity</key>
<value>0.56</value>
</param>
</block>
<connection>
<source_block_id>analog_noise_source_x_0</source_block_id>
<sink_block_id>blocks_add_xx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>1</sink_key>
</connection>
<connection>
<source_block_id>blocks_add_xx_0</source_block_id>
<sink_block_id>wifi_phy_hier_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>blocks_multiply_const_vxx_0</source_block_id>
<sink_block_id>blocks_add_xx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>foo_packet_pad2_0</source_block_id>
<sink_block_id>blocks_multiply_const_vxx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>foo_random_periodic_msg_source_0</source_block_id>
<sink_block_id>ieee802_11_mac_0</sink_block_id>
<source_key>out</source_key>
<sink_key>app in</sink_key>
</connection>
<connection>
<source_block_id>foo_wireshark_connector_0</source_block_id>
<sink_block_id>blocks_file_sink_0_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>ieee802_11_mac_0</source_block_id>
<sink_block_id>wifi_phy_hier_0</sink_block_id>
<source_key>phy out</source_key>
<sink_key>mac_in</sink_key>
</connection>
<connection>
<source_block_id>wifi_phy_hier_0</source_block_id>
<sink_block_id>foo_wireshark_connector_0</sink_block_id>
<source_key>mac_out</source_key>
<sink_key>in</sink_key>
</connection>
<connection>
<source_block_id>wifi_phy_hier_0</source_block_id>
<sink_block_id>foo_packet_pad2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
</flow_graph>
+2
View File
@@ -0,0 +1,2 @@
results/
sim.py
+30
View File
@@ -0,0 +1,30 @@
SHELL=/bin/bash
MESSAGES=100
ENCODING=0
PCAPFILES=$(shell python -c 'import itertools; import numpy as np; print(" ".join(["results/sim_%d_%.2f_%.1f_.pcap" % x for x in itertools.product(range(10), np.arange(.4, .7,.02), np.arange(-3, 10, .5))]))')
all: pdr.pdf
pdr.pdf: plot.py results/all.csv
python ./plot.py
sim.py: sim.grc
grcc -d . sim.grc
results/all.csv: $(PCAPFILES)
./parse.sh
%.pcap: sim.py
mkdir -p results
export GR_CONF_DEFAULT_MAX_MESSAGES=123
@echo $@
$(eval REPETITION=$(shell python -c "print \"$@\".split(\"_\")[1]"))
$(eval SENSITIVITY=$(shell python -c "print \"$@\".split(\"_\")[2]"))
$(eval SNR=$(shell python -c "print \"$@\".split(\"_\")[3]"))
@echo REPETITION=$(REPETITION)
@echo SENSITIVITY=$(SENSITiVITY)
@echo SNR=$(SNR)
./sim.py --messages=$(MESSAGES) --encoding=$(ENCODING) --sensitivity=$(SENSITIVITY) --snr=$(SNR) --repetition=$(REPETITION)
# gdb -ex run -ex quit --args python ./sim.py --messages=$(MESSAGES) --encoding=$(ENCODING) --sensitivity=$(SENSITIVITY) --snr=$(SNR) --repetition=$(REPETITION)
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
files=`ls results/*.pcap`
outfile=results/all.csv
rm -f ${outfile}
echo "repetition;sensitivity;snr;received"
echo "repetition;sensitivity;snr;received" > ${outfile}
for f in ${files}
do
repetition=`python -c "print \"${f}\".split(\"_\")[1]"`
sensitivity=`python -c "print \"${f}\".split(\"_\")[2]"`
snr=`python -c "print \"${f}\".split(\"_\")[3]"`
echo "file ${f} repetition ${repetition} sensitivity ${sensitivity} snr ${snr}"
rcvd=`tshark -r ${f} | wc -l | tr -d " "`
echo "${repetition};${sensitivity};${snr};${rcvd}"
echo "${repetition};${sensitivity};${snr};${rcvd}" >> ${outfile}
done
Binary file not shown.
+14
View File
@@ -0,0 +1,14 @@
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
pdr = pd.read_csv('./results/all.csv', sep=';')
a = pdr.groupby(['sensitivity', 'snr'])
b = a.agg({'received': np.mean}).reset_index()
c = b.pivot(index='snr', columns='sensitivity', values='received')
c.plot()
plt.savefig('pdr.pdf')
+993
View File
@@ -0,0 +1,993 @@
<?xml version='1.0' encoding='utf-8'?>
<?grc format='1' created='3.8.git'?>
<flow_graph>
<timestamp>Sat Feb 1 18:28:19 2014</timestamp>
<block>
<key>options</key>
<param>
<key>author</key>
<value></value>
</param>
<param>
<key>window_size</key>
<value>1280, 1024</value>
</param>
<param>
<key>category</key>
<value>Custom</value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>description</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(7, 4)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>generate_options</key>
<value>no_gui</value>
</param>
<param>
<key>hier_block_src_path</key>
<value>.:</value>
</param>
<param>
<key>id</key>
<value>sim</value>
</param>
<param>
<key>max_nouts</key>
<value>0</value>
</param>
<param>
<key>qt_qss_theme</key>
<value></value>
</param>
<param>
<key>realtime_scheduling</key>
<value></value>
</param>
<param>
<key>run_command</key>
<value>{python} -u {filename}</value>
</param>
<param>
<key>run_options</key>
<value>run</value>
</param>
<param>
<key>run</key>
<value>True</value>
</param>
<param>
<key>thread_safe_setters</key>
<value></value>
</param>
<param>
<key>title</key>
<value></value>
</param>
</block>
<block>
<key>variable</key>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 244)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>filename</value>
</param>
<param>
<key>value</key>
<value>"results/sim_%d_%.2f_%.1f_.pcap" % (repetition, sensitivity, snr)</value>
</param>
</block>
<block>
<key>variable</key>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 85)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>out_buf_size</value>
</param>
<param>
<key>value</key>
<value>96000</value>
</param>
</block>
<block>
<key>blocks_file_sink</key>
<param>
<key>append</key>
<value>False</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>1</value>
</param>
<param>
<key>file</key>
<value>filename</value>
</param>
<param>
<key>_coordinate</key>
<value>(112, 358)</value>
</param>
<param>
<key>_rotation</key>
<value>180</value>
</param>
<param>
<key>id</key>
<value>blocks_file_sink_0</value>
</param>
<param>
<key>type</key>
<value>byte</value>
</param>
<param>
<key>unbuffered</key>
<value>True</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
</block>
<block>
<key>blocks_multiply_const_vxx</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>const</key>
<value>(10**(snr/10.0))**.5</value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(696, 548)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>blocks_multiply_const_vxx_0</value>
</param>
<param>
<key>type</key>
<value>complex</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>vlen</key>
<value>1</value>
</param>
</block>
<block>
<key>channels_channel_model</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>block_tags</key>
<value>False</value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>epsilon</key>
<value>1.0</value>
</param>
<param>
<key>freq_offset</key>
<value>0</value>
</param>
<param>
<key>_coordinate</key>
<value>(928, 520)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>channels_channel_model_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>noise_voltage</key>
<value>1</value>
</param>
<param>
<key>seed</key>
<value>repetition</value>
</param>
<param>
<key>taps</key>
<value>1.0</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>1</value>
</param>
<param>
<key>_coordinate</key>
<value>(208, 6)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>encoding</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>e</value>
</param>
<param>
<key>type</key>
<value>intx</value>
</param>
<param>
<key>value</key>
<value>0</value>
</param>
</block>
<block>
<key>foo_packet_pad2</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>debug</key>
<value>False</value>
</param>
<param>
<key>delay_sec</key>
<value>0.001</value>
</param>
<param>
<key>delay</key>
<value>False</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(480, 520)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>foo_packet_pad2_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>out_buf_size</value>
</param>
<param>
<key>pad_front</key>
<value>2000</value>
</param>
<param>
<key>pad_tail</key>
<value>2000</value>
</param>
</block>
<block>
<key>foo_random_periodic_msg_source</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>debug</key>
<value>False</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(472, 184)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>foo_random_periodic_msg_source_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>msg_len</key>
<value>pdu_len - 24</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>num</key>
<value>messages</value>
</param>
<param>
<key>interval</key>
<value>5</value>
</param>
<param>
<key>quit</key>
<value>True</value>
</param>
<param>
<key>seed</key>
<value>repetition</value>
</param>
</block>
<block>
<key>foo_wireshark_connector</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>debug</key>
<value>False</value>
</param>
<param>
<key>_enabled</key>
<value>1</value>
</param>
<param>
<key>_coordinate</key>
<value>(320, 365)</value>
</param>
<param>
<key>_rotation</key>
<value>180</value>
</param>
<param>
<key>id</key>
<value>foo_wireshark_connector_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>tech</key>
<value>127</value>
</param>
</block>
<block>
<key>ieee802_11_mac</key>
<param>
<key>bss_mac</key>
<value>[0xff, 0xff, 0xff, 0xff, 0xff, 0xff]</value>
</param>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>dst_mac</key>
<value>[0x42, 0x42, 0x42, 0x42, 0x42, 0x42]</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(800, 220)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>ieee802_11_mac_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>src_mac</key>
<value>[0x23, 0x23, 0x23, 0x23, 0x23, 0x23]</value>
</param>
</block>
<block>
<key>import</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 148)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>import_0</value>
</param>
<param>
<key>import</key>
<value>import math</value>
</param>
</block>
<block>
<key>import</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(8, 196)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>import_0_0</value>
</param>
<param>
<key>import</key>
<value>import random</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(576, 6)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>interval</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>i</value>
</param>
<param>
<key>type</key>
<value>eng_float</value>
</param>
<param>
<key>value</key>
<value>400</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(672, 6)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>messages</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>m</value>
</param>
<param>
<key>type</key>
<value>intx</value>
</param>
<param>
<key>value</key>
<value>10</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(392, 6)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>pdu_len</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>l</value>
</param>
<param>
<key>type</key>
<value>intx</value>
</param>
<param>
<key>value</key>
<value>435</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(296, 6)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>repetition</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>r</value>
</param>
<param>
<key>type</key>
<value>intx</value>
</param>
<param>
<key>value</key>
<value>23</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(760, 6)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>sensitivity</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>S</value>
</param>
<param>
<key>type</key>
<value>eng_float</value>
</param>
<param>
<key>value</key>
<value>0.58</value>
</param>
</block>
<block>
<key>parameter</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(480, 6)</value>
</param>
<param>
<key>_rotation</key>
<value>0</value>
</param>
<param>
<key>id</key>
<value>snr</value>
</param>
<param>
<key>label</key>
<value></value>
</param>
<param>
<key>short_id</key>
<value>s</value>
</param>
<param>
<key>type</key>
<value>eng_float</value>
</param>
<param>
<key>value</key>
<value>10</value>
</param>
</block>
<block>
<key>wifi_phy_hier</key>
<param>
<key>alias</key>
<value></value>
</param>
<param>
<key>comment</key>
<value></value>
</param>
<param>
<key>affinity</key>
<value></value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
<key>_coordinate</key>
<value>(792, 377)</value>
</param>
<param>
<key>_rotation</key>
<value>180</value>
</param>
<param>
<key>id</key>
<value>wifi_phy_hier_0</value>
</param>
<param>
<key>maxoutbuf</key>
<value>0</value>
</param>
<param>
<key>minoutbuf</key>
<value>0</value>
</param>
<param>
<key>bandwidth</key>
<value>10e6</value>
</param>
<param>
<key>chan_est</key>
<value>0</value>
</param>
<param>
<key>encoding</key>
<value>encoding</value>
</param>
<param>
<key>frequency</key>
<value>5.89e9</value>
</param>
<param>
<key>sensitivity</key>
<value>sensitivity</value>
</param>
</block>
<connection>
<source_block_id>blocks_multiply_const_vxx_0</source_block_id>
<sink_block_id>channels_channel_model_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>channels_channel_model_0</source_block_id>
<sink_block_id>wifi_phy_hier_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>foo_packet_pad2_0</source_block_id>
<sink_block_id>blocks_multiply_const_vxx_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>foo_random_periodic_msg_source_0</source_block_id>
<sink_block_id>ieee802_11_mac_0</sink_block_id>
<source_key>out</source_key>
<sink_key>app in</sink_key>
</connection>
<connection>
<source_block_id>foo_wireshark_connector_0</source_block_id>
<sink_block_id>blocks_file_sink_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
<connection>
<source_block_id>ieee802_11_mac_0</source_block_id>
<sink_block_id>wifi_phy_hier_0</sink_block_id>
<source_key>phy out</source_key>
<sink_key>mac_in</sink_key>
</connection>
<connection>
<source_block_id>wifi_phy_hier_0</source_block_id>
<sink_block_id>foo_wireshark_connector_0</sink_block_id>
<source_key>mac_out</source_key>
<sink_key>in</sink_key>
</connection>
<connection>
<source_block_id>wifi_phy_hier_0</source_block_id>
<sink_block_id>foo_packet_pad2_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
</flow_graph>
+1
View File
@@ -21,6 +21,7 @@
find_package(SWIG) find_package(SWIG)
find_package(PythonLibs 2) find_package(PythonLibs 2)
if(NOT SWIG_FOUND OR NOT PYTHONLIBS_FOUND) if(NOT SWIG_FOUND OR NOT PYTHONLIBS_FOUND)
message(FATAL_ERROR "Python or Swig not found (or version not supported).")
return() return()
endif() endif()
include(GrSwig) include(GrSwig)
+57 -34
View File
@@ -22,57 +22,80 @@
%include "ieee802_11_swig_doc.i" %include "ieee802_11_swig_doc.i"
%{ %{
#include "gnuradio/digital/packet_header_default.h"
#include "ieee802-11/chunks_to_symbols.h" #include "ieee802-11/chunks_to_symbols.h"
#include "ieee802-11/constellations.h"
#include "ieee802-11/decode_mac.h"
#include "ieee802-11/ether_encap.h" #include "ieee802-11/ether_encap.h"
#include "ieee802-11/frame_equalizer.h"
#include "ieee802-11/mac.h"
#include "ieee802-11/mapper.h"
#include "ieee802-11/moving_average_cc.h" #include "ieee802-11/moving_average_cc.h"
#include "ieee802-11/moving_average_ff.h" #include "ieee802-11/moving_average_ff.h"
#include "ieee802-11/ofdm_decode_mac.h" #include "ieee802-11/parse_mac.h"
#include "ieee802-11/ofdm_decode_signal.h" #include "ieee802-11/signal_field.h"
#include "ieee802-11/ofdm_equalize_symbols.h" #include "ieee802-11/sync_long.h"
#include "ieee802-11/ofdm_mac.h" #include "ieee802-11/sync_short.h"
#include "ieee802-11/ofdm_mapper.h"
#include "ieee802-11/ofdm_parse_mac.h"
#include "ieee802-11/ofdm_sync_long.h"
#include "ieee802-11/ofdm_sync_short.h"
#include "ieee802-11/wifi_edca.h"
#include "ieee802-11/wifi_signal_field.h"
%} %}
%include "gnuradio/digital/packet_header_default.h" %include "gnuradio/digital/packet_header_default.h"
%ignore gr::digital::constellation_bpsk;
%ignore gr::digital::constellation_qpsk;
%ignore gr::digital::constellation_16qam;
%include "gnuradio/digital/constellation.h"
%include "ieee802-11/chunks_to_symbols.h" %include "ieee802-11/chunks_to_symbols.h"
%include "ieee802-11/constellations.h"
%include "ieee802-11/decode_mac.h"
%include "ieee802-11/ether_encap.h" %include "ieee802-11/ether_encap.h"
%include "ieee802-11/frame_equalizer.h"
%include "ieee802-11/mac.h"
%include "ieee802-11/mapper.h"
%include "ieee802-11/moving_average_cc.h" %include "ieee802-11/moving_average_cc.h"
%include "ieee802-11/moving_average_ff.h" %include "ieee802-11/moving_average_ff.h"
%include "ieee802-11/ofdm_decode_mac.h" %include "ieee802-11/parse_mac.h"
%include "ieee802-11/ofdm_decode_signal.h" %include "ieee802-11/signal_field.h"
%include "ieee802-11/ofdm_equalize_symbols.h" %include "ieee802-11/sync_long.h"
%include "ieee802-11/ofdm_mac.h" %include "ieee802-11/sync_short.h"
%include "ieee802-11/ofdm_mapper.h"
%include "ieee802-11/ofdm_parse_mac.h"
%include "ieee802-11/ofdm_sync_long.h"
%include "ieee802-11/ofdm_sync_short.h"
%include "ieee802-11/wifi_edca.h"
%include "ieee802-11/wifi_signal_field.h"
GR_SWIG_BLOCK_MAGIC2(ieee802_11, chunks_to_symbols); GR_SWIG_BLOCK_MAGIC2(ieee802_11, chunks_to_symbols);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, decode_mac);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, ether_encap); GR_SWIG_BLOCK_MAGIC2(ieee802_11, ether_encap);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, frame_equalizer);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, mac);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, mapper);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, moving_average_cc); GR_SWIG_BLOCK_MAGIC2(ieee802_11, moving_average_cc);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, moving_average_ff); GR_SWIG_BLOCK_MAGIC2(ieee802_11, moving_average_ff);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, ofdm_decode_mac); GR_SWIG_BLOCK_MAGIC2(ieee802_11, parse_mac);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, ofdm_decode_signal); GR_SWIG_BLOCK_MAGIC2(ieee802_11, sync_long);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, ofdm_equalize_symbols); GR_SWIG_BLOCK_MAGIC2(ieee802_11, sync_short);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, ofdm_mac);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, ofdm_mapper);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, ofdm_parse_mac);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, ofdm_sync_long);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, ofdm_sync_short);
GR_SWIG_BLOCK_MAGIC2(ieee802_11, wifi_edca);
%template(wifi_signal_field_sptr) boost::shared_ptr<gr::ieee802_11::wifi_signal_field>; %template(signal_field_sptr) boost::shared_ptr<gr::ieee802_11::signal_field>;
%pythoncode %{ %pythoncode %{
wifi_signal_field_sptr.__repr__ = lambda self: "<wifi_signal_field>" signal_field_sptr.__repr__ = lambda self: "<signal_field>"
wifi_signal_field = wifi_signal_field .make; signal_field = signal_field.make;
%}
%template(constellation_bpsk_sptr) boost::shared_ptr<gr::ieee802_11::constellation_bpsk>;
%pythoncode %{
constellation_bpsk_sptr.__repr__ = lambda self: "<constellation BPSK>"
constellation_bpsk = constellation_bpsk.make;
%}
%template(constellation_qpsk_sptr) boost::shared_ptr<gr::ieee802_11::constellation_qpsk>;
%pythoncode %{
constellation_qpsk_sptr.__repr__ = lambda self: "<constellation QPSK>"
constellation_qpsk = constellation_qpsk.make;
%}
%template(constellation_16qam_sptr) boost::shared_ptr<gr::ieee802_11::constellation_16qam>;
%pythoncode %{
constellation_16qam_sptr.__repr__ = lambda self: "<constellation 16QAM>"
constellation_16qam = constellation_16qam.make;
%}
%template(constellation_64qam_sptr) boost::shared_ptr<gr::ieee802_11::constellation_64qam>;
%pythoncode %{
constellation_64qam_sptr.__repr__ = lambda self: "<constellation 64QAM>"
constellation_64qam = constellation_64qam.make;
%} %}
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

-43
View File
@@ -1,43 +0,0 @@
dB2lin <- function(x) { 10^(x/10) }
gain.levels <- 0:46 * 2
gains <- dB2lin(gain.levels)
ref.level <- 1/0.03125 # the level we want to tune to
ref.gain <- gains[which(gain.levels == 46)] # idle gain setting
abs.level <- ref.level * ref.gain / gains
abs.level.int <- round(abs.level * 2**15)
lna.level <- c(0, 16, 30)
lna.conf <- c(0, 64, 96)
cat('if signed(power_in) > ', abs.level.int[1], ' then
a <= std_logic_vector(to_unsigned(0, 7));\n');
last = abs.level.int[1]
for(i in 2:length(abs.level.int)) {
if(abs.level.int[i] == last) {
next
}
last = abs.level.int[i];
gdb = gain.levels[i]
lna.index = max(which(lna.level <= gdb))
gdb = gdb - lna.level[lna.index]
lna = lna.conf[lna.index]
gdb = floor(gdb / 2)
cat('elsif signed(power_in) > ', last, ' then
a <= std_logic_vector(to_unsigned(', lna + gdb, ', 7));\n');
}
# --if signed(power_in) > 2**24 then
# -- a <= std_logic_vector(to_unsigned(0, 7));
# --elsif signed(power_in) > 2**16 then
# -- a <= std_logic_vector(to_unsigned(32, 7));
# --else
# -- a <= std_logic_vector(to_unsigned(127, 7));
# --end if;
+92
View File
@@ -0,0 +1,92 @@
#!/usr/bin/env python
channels = [
### 11g
1, 2412e6, "11g",
2, 2417e6, "11g",
3, 2422e6, "11g",
4, 2427e6, "11g",
5, 2432e6, "11g",
6, 2437e6, "11g",
7, 2442e6, "11g",
8, 2447e6, "11g",
9, 2452e6, "11g",
10, 2457e6, "11g",
11, 2462e6, "11g",
12, 2467e6, "11g",
13, 2472e6, "11g",
14, 2484e6, "11g",
### 11a
34, 5170e6, "11a",
36, 5180e6, "11a",
38, 5190e6, "11a",
40, 5200e6, "11a",
42, 5210e6, "11a",
44, 5220e6, "11a",
46, 5230e6, "11a",
48, 5240e6, "11a",
50, 5250e6, "11a",
52, 5260e6, "11a",
54, 5270e6, "11a",
56, 5280e6, "11a",
58, 5290e6, "11a",
60, 5300e6, "11a",
62, 5310e6, "11a",
64, 5320e6, "11a",
100, 5500e6, "11a",
102, 5510e6, "11a",
104, 5520e6, "11a",
106, 5530e6, "11a",
108, 5540e6, "11a",
110, 5550e6, "11a",
112, 5560e6, "11a",
114, 5570e6, "11a",
116, 5580e6, "11a",
118, 5590e6, "11a",
120, 5600e6, "11a",
122, 5610e6, "11a",
124, 5620e6, "11a",
126, 5630e6, "11a",
128, 5640e6, "11a",
132, 5660e6, "11a",
134, 5670e6, "11a",
136, 5680e6, "11a",
138, 5690e6, "11a",
140, 5700e6, "11a",
142, 5710e6, "11a",
144, 5720e6, "11a",
149, 5745e6, "11a (SRD)",
151, 5755e6, "11a (SRD)",
153, 5765e6, "11a (SRD)",
155, 5775e6, "11a (SRD)",
157, 5785e6, "11a (SRD)",
159, 5795e6, "11a (SRD)",
161, 5805e6, "11a (SRD)",
165, 5825e6, "11a (SRD)",
### 11p
172, 5860e6, "11p",
174, 5870e6, "11p",
176, 5880e6, "11p",
178, 5890e6, "11p",
180, 5900e6, "11p",
182, 5910e6, "11p",
184, 5920e6, "11p"
]
labels = []
freqs = []
for i in range(0, len(channels), 3):
labels.append(repr(channels[i]).rjust(3) + " | " + repr(channels[i+1]/1e6) + " | " + channels[i+2])
freqs.append(channels[i+1])
print labels
print freqs
+96
View File
@@ -0,0 +1,96 @@
#!/usr/bin/env python
import sys
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import ieee802_11
###############################################
# 16-QAM
###############################################
c = ieee802_11.constellation_16qam()
a = np.array(c.points())
p = np.average(np.abs(a)**2)
level = .1**.5
print "16-QAM, average power: {0:.4f}".format(p)
plt.scatter(a.real, a.imag)
for i, x in enumerate(a):
s = "{0:04b}".format(i)[::-1]
plt.text(x.real, x.imag+0.1, s, ha='center')
plt.show()
#######################
# test decison maker
#######################
N = 1000
data = np.random.randint(0, 16, N)
orig_const = a[data]
noisy_const = orig_const + np.random.sample(N) * 2 * level - level +\
np.random.sample(N) * 2j * level - level * 1j
rx = np.array(map(lambda x: c.decision_maker_v([x]), noisy_const))
rx_const = a[rx]
if any(rx != data):
print "16-QAM: data does not match."
else:
print "16-QAM: points decoded successfully."
plt.scatter(a.real, a.imag)
plt.scatter(noisy_const.real, noisy_const.imag, marker='x')
for d, a, b in zip(rx, rx_const, noisy_const):
plt.plot([a.real, b.real], [a.imag, b.imag], color=mpl.cm.hsv(d/16.0))
plt.show()
###############################################
# 64-QAM
###############################################
c = ieee802_11.constellation_64qam()
a = np.array(c.points())
p = np.average(np.abs(a)**2)
level = (1.0/42)**.5
print "64-QAM, average power: {0:.4f}".format(p)
plt.scatter(a.real, a.imag)
for i, x in enumerate(a):
s = "{0:06b}".format(i)[::-1]
plt.text(x.real, x.imag+0.06, s, ha='center')
plt.show()
#######################
# test decison maker
#######################
N = 1000
data = np.random.randint(0, 64, N)
orig_const = a[data]
noisy_const = orig_const + np.random.sample(N) * 2 * level - level +\
np.random.sample(N) * 2j * level - level * 1j
rx = np.array(map(lambda x: c.decision_maker_v([x]), noisy_const))
rx_const = a[rx]
if any(rx != data):
print "16-QAM: data does not match."
else:
print "16-QAM: points decoded successfully."
plt.scatter(a.real, a.imag)
plt.scatter(noisy_const.real, noisy_const.imag, marker='x')
for d, a, b in zip(rx, rx_const, noisy_const):
plt.plot([a.real, b.real], [a.imag, b.imag], color=mpl.cm.hsv(d/64.0))
plt.show()

Some files were not shown because too many files have changed in this diff Show More